gl4es icon indicating copy to clipboard operation
gl4es copied to clipboard

Shaders after shadercov question

Open kas1e opened this issue 4 years ago • 64 comments

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!

kas1e avatar Jan 18 '21 14:01 kas1e

Btw, version 130 and version 140 also seem fine to compile that shader. Just not 100 or 120

kas1e avatar Jan 18 '21 14:01 kas1e

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?

ptitSeb avatar Jan 18 '21 15:01 ptitSeb

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 ?

kas1e avatar Jan 18 '21 15:01 kas1e

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 ?

kas1e avatar Jan 18 '21 15:01 kas1e

Btw, just changing att *= 500; to att *= 500.0makes it works!

kas1e avatar Jan 18 '21 15:01 kas1e

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.

ptitSeb avatar Jan 18 '21 15:01 ptitSeb

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 ?

kas1e avatar Jan 18 '21 16:01 kas1e

Depends on how long and unambiguous is the sequence. att *= 500; is a bit short, so I'll probably take previous line too.

ptitSeb avatar Jan 18 '21 16:01 ptitSeb

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 ?

kas1e avatar Jan 18 '21 16:01 kas1e

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.

ptitSeb avatar Jan 18 '21 17:01 ptitSeb

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 ?

kas1e avatar Jan 18 '21 19:01 kas1e

Yep, it's that simple because I designed it to be easy to add more hack :)

ptitSeb avatar Jan 18 '21 19:01 ptitSeb

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 ?:)

kas1e avatar Jan 18 '21 19:01 kas1e

Spaces/tabs also taken into account I assume?

kas1e avatar Jan 18 '21 19:01 kas1e

Yes, sapce and Tabs are differents, and so are new line (not relevent here).

ptitSeb avatar Jan 18 '21 19:01 ptitSeb

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?

kas1e avatar Jan 18 '21 19:01 kas1e

Ah damn crap, we change ORIGINAL lines, not shaderconv generated :))

kas1e avatar Jan 18 '21 20:01 kas1e

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 ?

kas1e avatar Jan 18 '21 20:01 kas1e

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...

ptitSeb avatar Jan 18 '21 20:01 ptitSeb

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. 

kas1e avatar Jan 18 '21 20:01 kas1e

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.

kas1e avatar Jan 18 '21 20:01 kas1e

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 ?

kas1e avatar Jan 18 '21 21:01 kas1e

then try bloom/=float(pass)

ptitSeb avatar Jan 18 '21 21:01 ptitSeb

//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?

ptitSeb avatar Jan 18 '21 21:01 ptitSeb

dunno, just mimic shaderconv resutls :) will try that one now.

kas1e avatar Jan 18 '21 21:01 kas1e

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.

kas1e avatar Jan 18 '21 21:01 kas1e

for bloom/=float(pass) : sytax error, unexpected RIGHT_PAREN, expecting LEFT_PAREN

kas1e avatar Jan 18 '21 21:01 kas1e

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.

kas1e avatar Jan 18 '21 21:01 kas1e

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 any varying medium vec4 gl_TexCoord or varying medium vec4 _gl4es_TexCoord_0. So it also fails.

That's odd. Maybe there is a bug in shaderconv

ptitSeb avatar Jan 18 '21 21:01 ptitSeb

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 :)

kas1e avatar Jan 18 '21 22:01 kas1e