So I have this fragment shader, which was working great until I refactored some logic out into a separate function. I want to be able to call it multiple times to layer different versions of the effect on top of each other.
However, as soon as I created this custom function, the shader starts throwing the error:
ERROR: 0:33: 'grid' : no matching overloaded function found
Which is wierd, because it appears to be compiling it as function. If I remove the return from grid() I get this error too:
ERROR: 0:36: '' : function does not return a value: grid
So what am I missing here about declaring functions?
Full shader here:
uniform float brightness;
uniform float shiftX;
uniform float shiftY;
uniform vec4 color;
varying vec3 vPos;
void main() {
gl_FragColor = vec4( grid(200.0), 0.0, 0.0, 1.0 );
}
float grid(float size) {
float x = pow(abs(0.5 - mod(vPos.x + shiftX, 200.0) / 200.0), 4.0);
float y = pow(abs(0.5 - mod(vPos.y + shiftY, 200.0) / 200.0), 4.0);
return (x+y) * 5.0 * pow(brightness, 2.0);
}
You either have to put the grid function before the main or forward declare it as you would in c.
Such as:
float grid(float size);
before the main method.
Related
The shader I've converted below throws the following errors in LibGDX with Opengl 2.0:
ERROR: 0:08: '<<' does not operate on 'int' and 'int'
ERROR: 0:23: No matching function for call to mod(int, int)
ERROR: 0:24: Invalid call of undeclared identifier 'textureLod'
Obviously I commented out and replaced certain parts to see the errors further down but the errors should be all the problems it has.
varying vec4 v_color;
varying vec2 v_texCoords;
uniform sampler2D u_texture;
uniform vec2 resolution;
const int samples = 35, LOD = 2, sLOD = 1 << LOD;//error here
const float sigma = float(samples) * .25;
float gaussian(vec2 i) {
return exp( -.5* dot(i/=sigma,i) ) / ( 6.28 * sigma*sigma );
}
void main() {
vec2 u = gl_FragCoord.xy/resolution.xy;
vec4 o = vec4(0);
int s = samples/sLOD;
vec2 scale = vec2(1,1);
for ( int i = 0; i < s*s; i++ ) {
vec2 d = vec2(mod(i,s), i/s)*float(sLOD) - float(samples)/2.;//error here
o += gaussian(d) * textureLod( u_texture, u + scale * d , float(LOD) );//error here
}
gl_FragColor = v_color * texture2D(u_texture, v_texCoords);//simply outputs default image at the moment since the above has errors
}
There's not really any easy or good way to use anything higher than opengl 2.0 in LibGDX but I'm wondering if there's a workaround or alternative to any of these commands. Not sure particularly why mod doesn't work - it only works with float ?
What obvious thing am I missing? I'm trying to compile/run this vertex shader:
// an attribute will receive data from a buffer
attribute vec2 a_position;
uniform vec2 u_resolution;
varying vec4 v_color;
// all shaders have a main function
void main() {
// convert the position from pixels to 0.0 to 1.0
vec2 zeroToOne = a_position / u_resolution;
// convert from 0->1 to 0->2
vec2 zeroToTwo = zeroToOne * 2.0;
// convert from 0->2 to -1->+1 (clip space)
vec2 clipSpace = zeroToTwo - 1.0;
gl_Position = vec4(clipSpace, 0, 1);
vec3 c = hsv2rgb(vec3(0.5, 0.5, 0.5));
/*temporary*/ v_color = gl_Position * 0.5 + 0.5;
gl_PointSize = 1.0;
}
// All components are in the range [0…1], including hue.
vec3 hsv2rgb(vec3 c)
{
vec4 K = vec4(1.0, 2.0 / 3.0, 1.0 / 3.0, 3.0);
vec3 p = abs(fract(c.xxx + K.xyz) * 6.0 - K.www);
return c.z * mix(K.xxx, clamp(p - K.xxx, 0.0, 1.0), c.y);
}
using code I found at From RGB to HSV in OpenGL GLSL but get the error:
https://webglfundamentals.org/webgl/lessons/webgl-boilerplate.html
webgl-utils.js:66 *** Error compiling shader '[object WebGLShader]':ERROR: 0:19: 'hsv2rgb' : no matching overloaded function found
ERROR: 0:19: '=' : dimension mismatch
ERROR: 0:19: '=' : cannot convert from 'const mediump float' to 'highp 3-component vector of float'
The error is specific to the hsv2rgb call. I have tried a number of things, including making the parameter a variable (i.e. adding vec3 v = vec3(0.5, 0.5, 0.5) and passing v into hsv2rgb), and making a skeleton hbv2rgb that simply returns its parameter. In the referenced SO post, I saw that another user seemed to have exactly the same problem, but I am properly passing in a vec3 rather than 3 floats.
If it makes any difference, here is the fragment shader as well:
// fragment shaders don't have a default precision so we need
// to pick one. mediump is a good default
precision mediump float;
varying vec4 v_color;
void main() {
// gl_FragColor is a special variable a fragment shader
// is responsible for setting
gl_FragColor = v_color;
}
From OpenGL ES Shading Language 1.00 Specification - 6.1 Function Definitions:
All functions must be either declared with a prototype or defined with a body before they are called.
Hence, you have to declare the function hsv2rgb before it is used the first time or you have to declare a function prototype:
vec3 hsv2rgb(vec3 c);
void main() {
// [...]
vec3 c = hsv2rgb(vec3(0.5, 0.5, 0.5));
// [...]
}
vec3 hsv2rgb(vec3 c)
{
vec4 K = vec4(1.0, 2.0 / 3.0, 1.0 / 3.0, 3.0);
vec3 p = abs(fract(c.xxx + K.xyz) * 6.0 - K.www);
return c.z * mix(K.xxx, clamp(p - K.xxx, 0.0, 1.0), c.y);
}
The problems come from the mandelbrot function:
vec3 mandelbrot (vec2 coord){
vec2 z0 = vec2(0.0, 0.0);
int number = fractal (z0, coord, 10000);
float v = float(number);
float factor = 0.0;
return paletize (v, factor);
}
int fractal (vec2 z0, vec2 c, int maxIterations){
//doesn't matter
}
vec3 paletize (float v, float factor){
doesn't matter
}
and here is the error message: https://gyazo.com/5516853ee2600b58a303fd609530fafe
fragment shader failed to compile: the error log is: ERROR:0:13 ´fractal´:no matching overloaded function found
ERROR:0.13: '=' : cannot convert from const float to mediump int
ERROR:0:19: ´paletize´: no matching overloaded function found
ERROR:0:19: ´return´: function return is not matching type:
Try moving your fractal and paletize functions over mandelbrot.
Is it possible to somehow modify this fragment shader so that it doesn't use the oes_texture_float extension? Because I get an error on the machine which is supposed to run a webgl animation.
I set up my scene using three.js webglrenderer and a cube with a shadermaterial applied to it. On My macbook pro, everything works fine, but on some windows machine I get the error "float textures not supported" (I've searched and found that this probably has to do with oes_texture_float extension)
So I'm guessing I need to change my fragment shader? Or am I missing the point completely?
<script type="x-shader/x-vertex" id="vertexshader">
// switch on high precision floats
#ifdef GL_ES
precision highp float;
#endif
void main() {
gl_Position = projectionMatrix * modelViewMatrix * vec4(position, 1.0);
}
</script>
<script type="x-shader/x-fragment" id="fragmentshader">
#ifdef GL_ES
precision mediump float;
#endif
#define PI 3.14159265
uniform float time;
uniform vec2 resolution;
float f(float x) {
return (sin(x * 1.50 * PI ) + 19.0);
}
float q(vec2 p) {
float s = (f(p.x + 0.85)) / 2.0;
float c = smoothstep(0.9, 1.20, 1.0 - abs(p.y - s));
return c;
}
vec3 aurora(vec2 p, float time) {
vec3 c1 = q( vec2(p.x, p.y / 0.051) + vec2(time / 3.0, -0.3)) * vec3(2.90, 0.50, 0.10);
vec3 c2 = q( vec2(p.x, p.y / 0.051) + vec2(time, -0.2)) * vec3(1.3, .6, 0.3);
vec3 c3 = q( vec2(p.x, p.y / 0.051) + vec2(time / 5.0, -0.5)) * vec3(1.7, 0.4, 0.20);
return c1+c2+c3;
}
void main( void ) {
vec2 p = ( gl_FragCoord.xy / resolution.xy );
vec3 c = aurora(p, time);
gl_FragColor = vec4(1.0-c, c);
}
</script>
EDIT: this has nothing to do with the floating point texture, but rather with something in my fragment shader. Three.js gives me the error: "Can't initialise shader, VALIDATE_STATUS"
"Or am I missing the point completely?" - Indeed you are. The shaders don't care about the underlying texture format (you don't even use any textures in those shaders you posted!), so they don't have anything to do with your problem.
It's the application code that uses a float texture somewhere and needs to be changed accordingly. But from the fact that your shader doesn't use any textures at all (and I guess you haven't explicitly created a float texture elsewhere), it's probably three.js' internals that need a float texture somewhere, maybe as render target. So you need to search for ways to disable this requirement if possible.
Unless it's a three.js ism you haven't defined projectionMatrix, modelViewMatrix, and position in your vertex shader.
Try adding
uniform mat4 projectionMatrix;
uniform mat4 modelViewMatrix;
attribute vec4 position;
To the top of the first shader?
I thought i had it working but I still can't figure out how to change a value in my vertex shader. What i do in opengl is the following, for each render:
//i bind my shader
shader.bind();
// Then trying to set the value in my vertex shader like so:
GLuint test = glGetUniformLocation(shader.id(), "Test");
glUniform1f(test, 6.0f);
// Do some other stuff like rendering an object
// ...
// then unbind shader
shader.unbind();
This is the value i want to change in my vertex shader:
uniform float Test = 0.66; // Doesn't work
//const float Test = 0.66; // Works
But my shader doesn't work when i try that, it renders my object black.
If i comment the glGetUniform(Location) part out and if use the float as a const instead of a uniform then my shader works fine. But i want to be able to change the value in my shader in each render. I though i had to use a uniform for that...?
Is there something i'm missing..??
EDIT:
Appearently i'm getting the following GLSL error:
non constant expression in initialization
So it must be constant in order to work... Does that mean there is no way to have this as a dynamic value..?
This is my Vertex Shader:
const float FresnelPower = 1.0;
uniform float Eta; // <---- MUST BE CONSTANT...
const float F = ((1.0-Eta) * (1.0-Eta)) / ((1.0+Eta) * (1.0+Eta));
varying vec3 Reflect;
varying vec3 Refract;
varying float Ratio;
void main()
{
vec4 ecPosition = gl_ModelViewMatrix * gl_Vertex;
vec3 ecPosition3 = ecPosition.xyz / ecPosition.w;
vec3 i = normalize(ecPosition3);
vec3 n = normalize(gl_NormalMatrix * gl_Normal);
Ratio = F + (1.0 - F) * pow((1.0 - dot(-i, n)), FresnelPower);
Refract = refract(i, n, Eta);
Refract = vec3(gl_TextureMatrix[0] * vec4(Refract, 1.0));
Reflect = reflect(i, n);
Reflect = vec3(gl_TextureMatrix[0] * vec4(Reflect, 1.0));
gl_Position = ftransform();
}
uniform float Eta; // <---- MUST BE CONSTANT...
When GLSL says "constant", what it means is a compile time constant. The value of Eta is certainly uniform within a particular draw call. But it is not constant, because it can change between draw calls. The compiler does not know what this value will be at compile time.
A const variable is a compile time constant. It therefore must be initialized with an expression consisting only of compile time constants. uniforms are not compile time constants, so you cannot initialize a const variable with them.
You must declare your uniform in the vertex shader like this:
uniform float Test;
Also, you have to call glUseProgram() with your program object handle before calling glUniform1f(), so make sure that's what your shader.bind() does. It's enough if you call glGetUniformLocation() once and cache the result. Also, check the errors of your OpenGL calls with glGetError() to ensure everything else is working correctly.
Replying to your edit, I think this line is your problem:
const float F = ((1.0-Eta) * (1.0-Eta)) / ((1.0+Eta) * (1.0+Eta));
const means compile time constant, as in, the value cannot be changed by a uniform. F can't be a constant because a uniform variable is not a (compile time) constant. Move the line that declares F to the body of main and remove the const qualifier. Then your shader should work.