Shaders after shadercov question
Another thing to discuss if you don't mind :)
Working on some games, and it has quite a big set of original OpenGL shaders. Now, when I run a game, it brings me from some shaders that:
Compiler message is
ERROR: 94:1: 'assign' : cannot convert from ' const int' to ' temp highp float'
ERROR: 135:0: '' : compilation terminated
ERROR: 2 compilation errors. No code generated.
I enabled LIBGL_LOGSHADERERROR, and that what I have:
original shader:
uniform sampler2D Texture0, Texture1, Texture2, Texture3;
varying vec3 Normal;
varying float fogFactor;
varying vec4 Position;
vec4 CelShading(int l)
{
// Get texture color
vec4 color = gl_LightModel.ambient * gl_Color * texture2D(Texture0, vec2(gl_TexCoord[0]));
// Light orientation
vec3 LightDir = vec3(gl_LightSource[l].position-Position);
float dotProduct = max(dot(normalize(LightDir), normalize(Normal)), 0.0);
// Light attenuation
float dist = length(LightDir);
float att = 1.0 / (gl_LightSource[l].constantAttenuation + gl_LightSource[l].quadraticAttenuation * dist * dist);
att *= 500;
// 'Tooning'
float toonFactor = dotProduct;
toonFactor *= att;
if (toonFactor < 0.2) toonFactor = clamp(toonFactor, 0.0, 0.05);
else if (toonFactor < 0.5) toonFactor = clamp(toonFactor, 0.2, 0.35);
else if (toonFactor < 0.95) toonFactor = clamp(toonFactor, 0.5, 0.65);
else toonFactor = clamp(toonFactor, 0.95, 1.0);
// Final color
vec4 diffuse = gl_LightSource[l].diffuse;
diffuse /= vec4(128, 128, 128, 1.0);
color += toonFactor * diffuse * gl_Color * texture2D(Texture0, vec2(gl_TexCoord[0]));
return color;
}
void main()
{
vec4 color = vec4(0.0, 0.0, 0.0, 0.0);
for (int i = 0; i < gl_MaxLights; i++)
{
color += CelShading(i);
}
// Rim light
vec3 eyePos = normalize(vec3(-Position));
float fresnel = max(dot(normalize(Normal), eyePos), 0.0);
if (fresnel < 0.4)
{
float rim = clamp((0.4 - fresnel) / 0.4, 0.0, 1.0);
color += color * rim;
}
color = mix(gl_Fog.color, color, fogFactor);
color.a = 0.5;
gl_FragColor = color;
}
ShaderConv one ready to use:
#version 100
precision highp float;
#define _gl4es_MaxLights 8
precision highp int;
varying lowp vec4 _gl4es_FrontColor;
varying mediump vec4 _gl4es_TexCoord_0;
struct _gl4es_LightSourceParameters
{
vec4 ambient;
vec4 diffuse;
vec4 specular;
vec4 position;
vec4 halfVector;
vec3 spotDirection;
float spotExponent;
float spotCutoff;
float spotCosCutoff;
float constantAttenuation;
float linearAttenuation;
float quadraticAttenuation;
};
uniform _gl4es_LightSourceParameters _gl4es_LightSource[_gl4es_MaxLights];
struct _gl4es_LightModelParameters {
vec4 ambient;
};
uniform _gl4es_LightModelParameters _gl4es_LightModel;
struct _gl4es_FogParameters {
lowp vec4 color;
mediump float density;
highp float start;
highp float end;
highp float scale;
};
uniform _gl4es_FogParameters _gl4es_Fog;
float clamp(float f, int a, int b) {
return clamp(f, float(a), float(b));
}
float clamp(float f, float a, int b) {
return clamp(f, a, float(b));
}
float clamp(float f, int a, float b) {
return clamp(f, float(a), b);
}
vec2 clamp(vec2 f, int a, int b) {
return clamp(f, float(a), float(b));
}
vec2 clamp(vec2 f, float a, int b) {
return clamp(f, a, float(b));
}
vec2 clamp(vec2 f, int a, float b) {
return clamp(f, float(a), b);
}
vec3 clamp(vec3 f, int a, int b) {
return clamp(f, float(a), float(b));
}
vec3 clamp(vec3 f, float a, int b) {
return clamp(f, a, float(b));
}
vec3 clamp(vec3 f, int a, float b) {
return clamp(f, float(a), b);
}
vec4 clamp(vec4 f, int a, int b) {
return clamp(f, float(a), float(b));
}
vec4 clamp(vec4 f, float a, int b) {
return clamp(f, a, float(b));
}
vec4 clamp(vec4 f, int a, float b) {
return clamp(f, float(a), b);
}
float max(float a, int b) {
return max(a, float(b));
}
float max(int a, float b) {
return max(float(a), b);
}
uniform sampler2D Texture0, Texture1, Texture2, Texture3;
varying vec3 Normal;
varying float fogFactor;
varying vec4 Position;
vec4 CelShading(int l)
{
vec4 color = _gl4es_LightModel.ambient * _gl4es_FrontColor * texture2D(Texture0, vec2(_gl4es_TexCoord_0));
vec3 LightDir = vec3(_gl4es_LightSource[l].position-Position);
float dotProduct = max(dot(normalize(LightDir), normalize(Normal)), 0.00000);
float dist = length(LightDir);
float att = 1.00000 / (_gl4es_LightSource[l].constantAttenuation + _gl4es_LightSource[l].quadraticAttenuation * dist * dist);
att *= 500;
float toonFactor = dotProduct;
toonFactor *= att;
if (toonFactor < 0.200000) toonFactor = clamp(toonFactor, 0.00000, 0.0500000);
else if (toonFactor < 0.500000) toonFactor = clamp(toonFactor, 0.200000, 0.350000);
else if (toonFactor < 0.950000) toonFactor = clamp(toonFactor, 0.500000, 0.650000);
else toonFactor = clamp(toonFactor, 0.950000, 1.00000);
vec4 diffuse = _gl4es_LightSource[l].diffuse;
diffuse /= vec4(128, 128, 128, 1.00000);
color += toonFactor * diffuse * _gl4es_FrontColor * texture2D(Texture0, vec2(_gl4es_TexCoord_0));
return color;
}
void main()
{
vec4 color = vec4(0.00000, 0.00000, 0.00000, 0.00000);
for (int i = 0; i < _gl4es_MaxLights; i++)
{
color += CelShading(i);
}
vec3 eyePos = normalize(vec3(-Position));
float fresnel = max(dot(normalize(Normal), eyePos), 0.00000);
if (fresnel < 0.400000)
{
float rim = clamp((0.400000 - fresnel) / 0.400000, 0.00000, 1.00000);
color += color * rim;
}
color = mix(_gl4es_Fog.color, color, fogFactor);
color.a = 0.500000;
gl_FragColor = color;
}
I give it a go through GLSlangvalidator , and it brings the same error.
Next what I do, is set the version to 120. Error changes, says:
ERROR: 1:1: '' : syntax error, unexpected IDENTIFIER
ERROR: 1 compilation errors. No code generated
But then, I set version 150, and it works! Compiles fine, all fine.
So questions are:
1). Do we need to set the version to 100 in gl4es for generated shaders from OpenGL ones? Shouldn't we just set 150 by default and be it? Or it did for a purpose?
2). If version 100 is done for purpose, can i somehow hack the gl4es, so i just will have gl4es build just for this game with version 150 ? I just tried to change in shaderconv.c that line:
static const char* GLESHeader[] = {
"#version 100\n%sprecision %s float;\nprecision %s int;\n",
on that:
static const char* GLESHeader[] = {
"#version 150\n%sprecision %s float;\nprecision %s int;\n",
and it leads to the massive amount of new errors, all shaders fail to compiles, etc. So seems just such a simple change as a non-go, maybe somewhere else (if it will work at all?).
thanks!
Btw, version 130 and version 140 also seem fine to compile that shader. Just not 100 or 120
Yes, version 100 is on purpose, as it's the only one supported by gles2.
I think the issue is with att *= 500; that should be att *= 500.0; instead.
Also, this line diffuse /= vec4(128, 128, 128, 1.0); is suspicious and should probably be diffuse /= vec4(128.0, 128.0, 128.0, 1.0);
I can try to add that to the hack part of gl4es. What game is this?
Its closed source game called "Worlds" , and it has quite lot of shaders .. But yeah, we can ad them as hacks, just how to check that this is "worlds" game ? Is your hacks based on the game's names ?
The game there : https://store.steampowered.com/app/304850/Worlds/ , maybe it works on gl4es/wine/bx86 already so you can test if the shaders works ?
Error of this kind happens when we have "very low" details set. The more details level set, the more shaders used. So you firstly may try with "very low" details, then just set "very high" (and restart of course, as it irrlicht), and see if it will bring more errors or not. But i hope maybe in end it will be just 1-2 hacks for all of them ?
Btw, just changing att *= 500; to att *= 500.0makes it works!
The hack is not based on game name, only on part of shader, but I like to keep a track on what game need what hack.
Aha got it, so it based just on the uniq sequence in hope that will never repeats anywhere. Uhm, but if we will have 10 different shaders with the same error, it should be 10 different hacks ?
Depends on how long and unambiguous is the sequence. att *= 500; is a bit short, so I'll probably take previous line too.
Yeah, let's try step by step, will see how many hacks it may needs.
But those things are fixable only by hacks, nothing like general solution in generated code can be done ?
General solution need a complete GLSL "compiler" in gl4es. That would be nice, and open the door to many more things, but it's a huge work and not planed for now.
Tested more shaders for the game: many of them have that error, but good for us it always seems att *= 500 stuf.
There is also another set of shaders brings different kind of errors:
ERROR: 73:1: '*' : wrong operand types: no operation '*' exists that takes a left-hand operand of type ' global highp 4-component vector of float' and a right operand of type ' const int' (or there is no acceptable conversion)
ERROR: 100:0: '' : compilation terminated
ERROR: 2 compilation errors. No code generated.
That for this kind of shader:
#version 100
precision highp float;
precision highp int;
varying mediump vec4 _gl4es_TexCoord_0;
varying mediump vec4 _gl4es_TexCoord_1;
struct _gl4es_LightModelParameters {
vec4 ambient;
};
uniform _gl4es_LightModelParameters _gl4es_LightModel;
struct _gl4es_FogParameters {
lowp vec4 color;
mediump float density;
highp float start;
highp float end;
highp float scale;
};
uniform _gl4es_FogParameters _gl4es_Fog;
float clamp(float f, int a, int b) {
return clamp(f, float(a), float(b));
}
float clamp(float f, float a, int b) {
return clamp(f, a, float(b));
}
float clamp(float f, int a, float b) {
return clamp(f, float(a), b);
}
vec2 clamp(vec2 f, int a, int b) {
return clamp(f, float(a), float(b));
}
vec2 clamp(vec2 f, float a, int b) {
return clamp(f, a, float(b));
}
vec2 clamp(vec2 f, int a, float b) {
return clamp(f, float(a), b);
}
vec3 clamp(vec3 f, int a, int b) {
return clamp(f, float(a), float(b));
}
vec3 clamp(vec3 f, float a, int b) {
return clamp(f, a, float(b));
}
vec3 clamp(vec3 f, int a, float b) {
return clamp(f, float(a), b);
}
vec4 clamp(vec4 f, int a, int b) {
return clamp(f, float(a), float(b));
}
vec4 clamp(vec4 f, float a, int b) {
return clamp(f, a, float(b));
}
vec4 clamp(vec4 f, int a, float b) {
return clamp(f, float(a), b);
}
float max(float a, int b) {
return max(a, float(b));
}
float max(int a, float b) {
return max(float(a), b);
}
uniform sampler2D Texture0, Texture1;
varying vec3 Normal;
varying float fogFactor;
varying vec4 Position;
float getLuminance(vec4 color)
{
return dot(color, vec4(0.299000, 0.587000, 0.114000, 0.00000));
}
void main()
{
vec4 texel0 = texture2D(Texture0, vec2(_gl4es_TexCoord_0));
vec4 texel1 = texture2D(Texture1, vec2(_gl4es_TexCoord_1));
texel1 = texel1 + _gl4es_LightModel.ambient * 2;
float tmp = texel1.r + texel1.g + texel1.b;
float factor = 0.00000;
if (tmp > 0.300000) factor = 0.950000;
else if (tmp > 0.200000) factor = 0.700000;
else if (tmp > 0.100000) factor = 0.500000;
else if (tmp > 0.0500000) factor = 0.300000;
else if (tmp > 0.0250000) factor = 0.100000;
else factor = 0.00000;
texel1 *= 7.00000;
vec4 color = texel0 * texel1 * factor;
vec3 eyePos = normalize(vec3(-Position));
float fresnel = max(dot(normalize(Normal), eyePos), 0.00000);
if (fresnel < 0.400000)
{
float rim = clamp((0.400000 - fresnel) / 0.400000, 0.00000, 1.00000);
float l = clamp(getLuminance(color), 0.00000, 1.00000);
l = 1.00000 - l;
color += color * rim * l;
}
color = mix(_gl4es_Fog.color, color, fogFactor);
gl_FragColor = color;
}
Issue there is line texel1 = texel1 + _gl4es_LightModel.ambient * 2;, once replaced on *2.0; then all compiles fine.
So far it seems we can just add 2 hacks, and it can be it.
Btw, adding of hack as it sees trivial: I just put one string (the original one), and then just "new" one in shader_hack.c, and no changes anywhere else need it ?
Yep, it's that simple because I designed it to be easy to add more hack :)
just tried at top that:
static const hack_t gl4es_hacks[] = {
// Worlds
//1
{"att *= 500;",
1,
{"att *= 500.0;",}},
//2
{"texel1 = texel1 + _gl4es_LightModel.ambient * 2;",
1,
{"texel1 = texel1 + _gl4es_LightModel.ambient * 2.0;"}},
Didn't swaps :) Maybe something still need to be done somewhere else ?:)
Spaces/tabs also taken into account I assume?
Yes, sapce and Tabs are differents, and so are new line (not relevent here).
Strange .. just copy+paste the line exactly from shader.. And from LIBGL_LOGSHADERERROR if it still spawns (because of other error for example) I should see that 2 changes on 2.0, right?
Ah damn crap, we change ORIGINAL lines, not shaderconv generated :))
Done with 3 hacks, now next shader which doesn't know how to fix (even version change dind't help):
ERROR: 56:1: 'texture2D' : no matching overloaded function found
ERROR: 56:1: '=' : cannot convert from ' const float' to ' temp highp 4-component vector of float'
ERROR: 108:0: '' : compilation terminated
ERROR: 3 compilation errors. No code generated.
That is the shader:
#version 100
precision highp float;
precision highp int;
varying mediump vec4 _gl4es_TexCoord_0;
float clamp(float f, int a, int b) {
return clamp(f, float(a), float(b));
}
float clamp(float f, float a, int b) {
return clamp(f, a, float(b));
}
float clamp(float f, int a, float b) {
return clamp(f, float(a), b);
}
vec2 clamp(vec2 f, int a, int b) {
return clamp(f, float(a), float(b));
}
vec2 clamp(vec2 f, float a, int b) {
return clamp(f, a, float(b));
}
vec2 clamp(vec2 f, int a, float b) {
return clamp(f, float(a), b);
}
vec3 clamp(vec3 f, int a, int b) {
return clamp(f, float(a), float(b));
}
vec3 clamp(vec3 f, float a, int b) {
return clamp(f, a, float(b));
}
vec3 clamp(vec3 f, int a, float b) {
return clamp(f, float(a), b);
}
vec4 clamp(vec4 f, int a, int b) {
return clamp(f, float(a), float(b));
}
vec4 clamp(vec4 f, float a, int b) {
return clamp(f, a, float(b));
}
vec4 clamp(vec4 f, int a, float b) {
return clamp(f, float(a), b);
}
uniform sampler2D Texture0;
varying vec4 Position;
vec4 interpolate(vec4 c0, vec4 c1, float f)
{
vec4 r = (c0 * (1.00000 - f)) + (c1 * f);
return r;
}
float getLuminance(vec4 color)
{
return dot(color, vec4(0.299000, 0.587000, 0.114000, 0.00000));
}
void main()
{
vec4 color = texture2D(Texture0, _gl4es_TexCoord_0);
color *= vec4(0.800000, 1.00000, 1.00000, 1.00000);
vec4 bloom = vec4(0);
vec4 bloomL = vec4(0);
int pass = 0;
int range = 5;
float th = 0.700000;
for (int j = -range; j <= range; j++)
{
for (int i = -range; i <= range; i++)
{
vec2 offset = vec2(i, j) * 0.00100000;
offset += _gl4es_TexCoord_0;
offset = clamp(offset, vec2(0.00000, 0.00000), vec2(1.00000, 1.00000));
vec4 add = texture2D(Texture0, offset);
bloom += add;
offset = vec2(i, j) * 0.00250000;
offset += _gl4es_TexCoord_0;
offset = clamp(offset, vec2(0.00000, 0.00000), vec2(1.00000, 1.00000));
add = texture2D(Texture0, offset);
float lum = getLuminance(add);
if (lum > th)
{
float factor = (lum - th) / (1.00000 - th);
bloomL += add * factor;
}
pass++;
}
}
bloom /= pass;
bloom *= 0.250000;
bloomL /= pass;
bloomL *= 0.500000;
float sFactor = (Position.y + 1.00000) / 2.00000;
sFactor *= 0.400000;
sFactor += 0.800000;
color *= 0.750000;
color *= sFactor;
gl_FragColor = color + bloom + bloomL;
}
Have a clue how to deal with this one ?
Ah damn crap, we change ORIGINAL lines, not shaderconv generated :))
Ah yes, I should have mentionned it!
For the other shader, the issue is that transformed line vec4 color = texture2D(Texture0, _gl4es_TexCoord_0);
it should be vec4 color = texture2D(Texture0, _gl4es_TexCoord_0.xy);
but again, you need the original line...
Yeah, replaced that line, but now for that shader still have those errors:
ERROR: 71:1: 'assign' : cannot convert from ' smooth in mediump 4-component vector of float' to ' temp highp 2-component vector of float'
ERROR: 107:0: '' : compilation terminated
ERROR: 2 compilation errors. No code generated.
replaced in 2 other places on .xy at the end, and then it fails seems so on bloom/=pass, which seems related to issues that bloom are vec4, but the pass is int.
Also find out, that when i add such hacks:
//4
{" vec4 color = texture2D(Texture0, gl_TexCoord[0]);",
1,
{" vec4 color = texture2D(Texture0, _gl4es_TexCoord_0.xy);"}},
//5
{" offset += gl_TexCoord[0];",
1,
{" offset += _gl4es_TexCoord_0.xy;"}},
In some generated shaders just disappear line varying medium vec4 _gl4es_TexCoord_0! Can be a bug in hack-insert stuff, or i just mess something ?
then try bloom/=float(pass)
//4 {" vec4 color = texture2D(Texture0, gl_TexCoord[0]);", 1, {" vec4 color = texture2D(Texture0, gl_TexCoord[0].xy);"}},
Why don't you use
//4
{" vec4 color = texture2D(Texture0, gl_TexCoord[0]);",
1,
{" vec4 color = texture2D(Texture0, gl_TexCoord[0].xy);"}},
Instead?
dunno, just mimic shaderconv resutls :) will try that one now.
Well, i do it because shaderconv do at top by default varying medium vec4 _gl4es_TexCoord_0, so if i put it as you wrote, then it will say that gl_TexCoord_0 undeclared identifier.
for bloom/=float(pass) : sytax error, unexpected RIGHT_PAREN, expecting LEFT_PAREN
Also if i just put everywhere gl_TexCoord[0].xy, it also says undeclared identifier, because in generated shaderconv shader there is no any varying medium vec4 gl_TexCoord or varying medium vec4 _gl4es_TexCoord_0. So it also fails.
for
bloom/=float(pass):sytax error, unexpected RIGHT_PAREN, expecting LEFT_PAREN
This should be correct syntax (execpt for the missing ;), it shoud work
Also if i just put everywhere
gl_TexCoord[0].xy, it also says undeclared identifier, because in generated shaderconv shader there is no anyvarying medium vec4 gl_TexCoordorvarying medium vec4 _gl4es_TexCoord_0. So it also fails.
That's odd. Maybe there is a bug in shaderconv
This should be correct syntax (execpt for the missing ;), it shoud work
Full line i have now are bloom/= (float)pass;, and bring that error. those are defined as : vec4 bloom = vec4(0); and int pass = 0;
That's odd. Maybe there is a bug in shaderconv
It seems so. At least when i just do that at the top:
static const hack_t gl4es_hacks[] = {
// Worlds
//1
{" att *= 500;",
1,
{" att *= 500.0;"}},
//2
{" texel1 = texel1 + gl_LightModel.ambient * 2;",
1,
{" texel1 = texel1 + gl_LightModel.ambient * 2.0;"}},
//3
{" vec4 ambient = gl_LightModel.ambient * 2;",
1,
{" vec4 ambient = gl_LightModel.ambient * 2.0;"}},
//4
{" vec4 color = texture2D(Texture0, gl_TexCoord[0]);",
1,
{" vec4 color = texture2D(Texture0, _gl4es_TexCoord_0.xy);"}},
//5
{" offset += gl_TexCoord[0];",
1,
{" offset += _gl4es_TexCoord_0.xy;"}},
Then some compiled shaders just didn't have anymore varying medium vec4 _gl4es_TexCoord_0 at all. But if i change it like you say (to gl_TexCoord instead), then, this varying medium vec4 _gl4es_TexCoord_0 are in generated shaders, but then it should be gl_TexCoord instead.
And I specially choose _gl4es_TexCoord_0 there, because of that varying medium vec4 _gl4es_TexCoord_0 at the top. If it only not disappear randomly :)