I don't have much experience with Shader or GLSL. I am trying to practice with them. To this end I'm trying to port this shader.
https://www.shadertoy.com/view/XsXGR7
Into a project to use with SFML. I am having issue doing this and I'm not sure what to do to start fixing the issues.
I messed around with the uniforms and a few varaiable but the shader itself keeps giving the same error message. That it won't compile. Not sure why, I assume it's because without converting it to work with SFML it's asking for input from OpenGL.
Shader file
uniform vec3 iResolution; // viewport resolution (in pixels)
uniform float iTime; // shader playback time (in seconds)
uniform float iTimeDelta; // render time (in seconds)
uniform int iFrame; // shader playback frame
uniform float iChannelTime[4]; // channel playback time (in seconds)
uniform vec3 iChannelResolution[4]; // channel resolution (in pixels)
uniform vec4 iMouse; // mouse pixel coords. xy: current (if MLB down), zw: click
uniform samplerXX iChannel0..3; // input channel. XX = 2D/Cube
uniform vec4 iDate; // (year, month, day, time in seconds)
uniform float iSampleRate; // sound sample rate (i.e., 44100)
void mainImage( out vec4 fragColor, in vec2 fragCoord )
{
vec3 waveParams = vec3( 10.0, 0.8, 0.1 );
vec2 tmp = vec2( iMouse.xy / iResolution.xy );
vec2 uv = fragCoord.xy / iResolution.xy;
vec2 texCoord = uv;
float distance = distance(uv, tmp);
if ( (distance <= ((iTime ) + waveParams.z )) && ( distance >= ((iTime ) - waveParams.z)) )
{
float diff = (distance - (iTime));
float powDiff = 1.0 - pow(abs(diff*waveParams.x), waveParams.y);
float diffTime = diff * powDiff;
vec2 diffUV = normalize(uv - tmp);
texCoord = uv + (diffUV * diffTime);
}
vec4 original = texture( iChannel0, texCoord);
fragColor = original;
}
Currently all the shader does is get loaded in.
shader.loadFromFile("ASSETS/SHADERS/Shockwave1.txt",sf::Shader::Fragment);
//load the shader
if (!shader.isAvailable()) {
std::cout << "The shader is not available\n";
}
Error message trying to load the above shader. No uniforms set, nothing is done with the shader aside from loading it.
Failed to compile fragment shader:
WARNING: 0:1 '' : #version directive missing
ERROR: 0:8 'iChannel0 : syntax error syntax error
Edit:
Having replaced "samplerXX" with "sampler2D" and inserted a void main() function the shader loads properly. Getting the code to work is now the issue.
The Main()
void main(out vec4 fragColor, in vec2 fragCoord )
{
vec3 waveParams = vec3( 10.0, 0.8, 0.1 );
vec2 tmp = vec2( iMouse.xy / iResolution.xy );
vec2 uv = fragCoord.xy / iResolution.xy;
vec2 texCoord = uv;
float distance = distance(uv, tmp);
if ( (distance <= ((iTime ) + waveParams.z )) && ( distance >= ((iTime ) - waveParams.z)) )
{
float diff = (distance - (iTime));
float powDiff = 1.0 - pow(abs(diff*waveParams.x), waveParams.y);
float diffTime = diff * powDiff;
vec2 diffUV = normalize(uv - tmp);
texCoord = uv + (diffUV * diffTime);
}
vec4 original = texture( iChannel0, texCoord);
fragColor = original;
}
This produces these errors
Failed to compile fragment shader:
WARNING: 0:1: '' : #version directive missing
WARNING: 0:32: 'function' : is not available in current GLSL version texture
ERROR: 0:34: 'main' : function cannot take any parameter(s)
WARNING: 0:53: 'function' : is not available in current GLSL version texture
While the main not taking parameters is straightforward I would like to know would values be passed in strictly using uniforms? I am not sure what the 'function' errors relate to.
Edit:
Main()
void main( )
{
vec2 fragCoord = vec2(20,20);
vec3 waveParams = vec3( 10.0, 0.8, 0.1 );
vec2 tmp = vec2( iMouse.xy / iResolution.xy );
vec2 uv = fragCoord.xy / iResolution.xy;
vec2 texCoord = uv;
float distance = distance(uv, tmp);
if ( (distance <= ((iTime ) + waveParams.z )) && ( distance >= ((iTime ) - waveParams.z)) )
{
float diff = (distance - (iTime));
float powDiff = 1.0 - pow(abs(diff*waveParams.x), waveParams.y);
float diffTime = diff * powDiff;
vec2 diffUV = normalize(uv - tmp);
texCoord = uv + (diffUV * diffTime);
}
vec4 original = texture( iChannel0, texCoord);
gl_FragColor = original;
}
Removing the main parameters, hardcode defining vec2 fragCoord as vec2(20,20) made the shader run without issue. My question now is this enough to output the shader effect? (Little experience with glsl, sorry if this is a dumb question)
gl_FragColor = original;
And if it is this seems to be the position of the pixel to be shaded. Is there a way to pass this in automatically?
vec2 fragCoord
Related
I have coded a fragment shader in vizard IDE and its not working. The code is free of compilation errors except for one which says, " ERROR: 0:? : 'variable' : is not available in current GLSL version gl_TexCoord."
FYI the gl_TexCoord is the output of the vertex shader which is in build to vizard. Can someone help me to fix it. here is the code:
#version 440
// All uniforms as provided by Vizard
uniform sampler2D vizpp_InputDepthTex; // Depth texture
uniform sampler2D vizpp_InputTex; // Color texture
uniform ivec2 vizpp_InputSize; // Render size of screen in pixels
uniform ivec2 vizpp_InputPixelSize; // Pixel size (1.0/vizpp_InputSize)
uniform mat4 osg_ViewMatrix; // View matrix of camera
uniform mat4 osg_ViewMatrixInverse; // Inverse of view matrix
// Your own uniforms
//uniform sampler2D u_texture;
//uniform sampler2D u_normalTexture;
uniform sampler2D g_FinalSSAO;
const bool onlyAO = false; //Only show AO pass for debugging
const bool externalBlur = false; //Store AO in alpha slot for a later blur
struct ASSAOConstants
{
vec2 ViewportPixelSize; // .zw == 1.0 / ViewportSize.xy
vec2 HalfViewportPixelSize; // .zw == 1.0 / ViewportHalfSize.xy
vec2 DepthUnpackConsts;
vec2 CameraTanHalfFOV;
vec2 NDCToViewMul;
vec2 NDCToViewAdd;
ivec2 PerPassFullResCoordOffset;
vec2 PerPassFullResUVOffset;
vec2 Viewport2xPixelSize;
vec2 Viewport2xPixelSize_x_025; // Viewport2xPixelSize * 0.25 (for fusing add+mul into mad)
float EffectRadius; // world (viewspace) maximum size of the shadow
float EffectShadowStrength; // global strength of the effect (0 - 5)
float EffectShadowPow;
float EffectShadowClamp;
float EffectFadeOutMul; // effect fade out from distance (ex. 25)
float EffectFadeOutAdd; // effect fade out to distance (ex. 100)
float EffectHorizonAngleThreshold; // limit errors on slopes and caused by insufficient geometry tessellation (0.05 to 0.5)
float EffectSamplingRadiusNearLimitRec; // if viewspace pixel closer than this, don't enlarge shadow sampling radius anymore (makes no sense to grow beyond some distance, not enough samples to cover everything, so just limit the shadow growth; could be SSAOSettingsFadeOutFrom * 0.1 or less)
float DepthPrecisionOffsetMod;
float NegRecEffectRadius; // -1.0 / EffectRadius
float LoadCounterAvgDiv; // 1.0 / ( halfDepthMip[SSAO_DEPTH_MIP_LEVELS-1].sizeX * halfDepthMip[SSAO_DEPTH_MIP_LEVELS-1].sizeY )
float AdaptiveSampleCountLimit;
float InvSharpness;
int PassIndex;
vec2 QuarterResPixelSize; // used for importance map only
vec4 PatternRotScaleMatrices[5];
float NormalsUnpackMul;
float NormalsUnpackAdd;
float DetailAOStrength;
float Dummy0;
mat4 NormalsWorldToViewspaceMatrix;
};
uniform ASSAOConstants g_ASSAOConsts;
float PSApply( in vec4 inPos, in vec2 inUV)
{ //inPos = gl_FragCoord;
float ao;
uvec2 pixPos = uvec2(inPos.xy);
uvec2 pixPosHalf = pixPos / uvec2(2, 2);
// calculate index in the four deinterleaved source array texture
int mx = int (pixPos.x % 2);
int my = int (pixPos.y % 2);
int ic = mx + my * 2; // center index
int ih = (1-mx) + my * 2; // neighbouring, horizontal
int iv = mx + (1-my) * 2; // neighbouring, vertical
int id = (1-mx) + (1-my)*2; // diagonal
vec2 centerVal = texelFetchOffset( g_FinalSSAO, ivec2(pixPosHalf), 0, ivec2(ic, 0 ) ).xy;
ao = centerVal.x;
if (true){ // change to 0 if you want to disable last pass high-res blur (for debugging purposes, etc.)
vec4 edgesLRTB = UnpackEdges( centerVal.y );
// convert index shifts to sampling offsets
float fmx = mx;
float fmy = my;
// in case of an edge, push sampling offsets away from the edge (towards pixel center)
float fmxe = (edgesLRTB.y - edgesLRTB.x);
float fmye = (edgesLRTB.w - edgesLRTB.z);
// calculate final sampling offsets and sample using bilinear filter
vec2 uvH = (inPos.xy + vec2( fmx + fmxe - 0.5, 0.5 - fmy ) ) * 0.5 * g_ASSAOConsts.HalfViewportPixelSize;
float aoH = textureLodOffset( g_FinalSSAO, uvH, 0, ivec2(ih , 0) ).x;
vec2 uvV = (inPos.xy + vec2( 0.5 - fmx, fmy - 0.5 + fmye ) ) * 0.5 * g_ASSAOConsts.HalfViewportPixelSize;
float aoV = textureLodOffset( g_FinalSSAO, uvV, 0, ivec2( iv , 0) ).x;
vec2 uvD = (inPos.xy + vec2( fmx - 0.5 + fmxe, fmy - 0.5 + fmye ) ) * 0.5 * g_ASSAOConsts.HalfViewportPixelSize;
float aoD = textureLodOffset( g_FinalSSAO, uvD, 0, ivec2( id , 0) ).x;
// reduce weight for samples near edge - if the edge is on both sides, weight goes to 0
vec4 blendWeights;
blendWeights.x = 1.0;
blendWeights.y = (edgesLRTB.x + edgesLRTB.y) * 0.5;
blendWeights.z = (edgesLRTB.z + edgesLRTB.w) * 0.5;
blendWeights.w = (blendWeights.y + blendWeights.z) * 0.5;
// calculate weighted average
float blendWeightsSum = dot( blendWeights, vec4( 1.0, 1.0, 1.0, 1.0 ) );
ao = dot( vec4( ao, aoH, aoV, aoD ), blendWeights ) / blendWeightsSum;
}
return ao;
}
void main(void)
{
// Get base values
vec2 texCoord = gl_TexCoord[0].st;
vec4 color = texture2D(vizpp_InputTex,texCoord);
float depth = texture2D(vizpp_InputDepthTex,texCoord).x;
// Do not calculate if nothing visible (for VR for instance)
if (depth>=1.0)
{
gl_FragColor = color;
return;
}
float ao = PSApply(gl_FragCoord, texCoord);
// Output the result
if(externalBlur) {
gl_FragColor.rgb = color.rgb;
gl_FragColor.a = ao;
}
else if(onlyAO) {
gl_FragColor.rgb = vec3(ao,ao,ao);
gl_FragColor.a = 1.0;
}
else {
gl_FragColor.rgb = ao*color.rgb;
gl_FragColor.a = 1.0;
}
}
gl_TexCoord is a deprecated Compatibility Profile Built-In Language Variables and is removed after GLSL Version 1.20.
If you want to use gl_TexCoord then you would have to use GLSL version 1.20 (#version 120).
But, you don't need the deprecated compatibility profile built-in language variable at all. Define a Vertex shader output texCoord and use this output rather than gl_TexCoord:
#version 440
out vec2 texCoord;
void main()
{
texCoord = ...;
// [...]
}
Specify a corresponding input in the fragment shader:
#version 440
in vec2 texCoord;
void main()
{
vec4 color = texture2D(vizpp_InputTex, texCoord.st);
// [...]
}
I've been following along with the OpenGL 4 Shading Language cookbook and have gotten a teapot rendering with bezier surfaces. The next step I'm attempting is to draw a wireframe over the surfaces using a geometry shader. The directions can be found here on pages 228-230. Following the code that is given, I've gotten the wireframe to display, however, I also have multiple fragments that flicker different shades of my material color.
An image of this can be seen
I have narrowed down the possible issues and have discovered that for some reason, when I perform my triangle height calculations, I am getting variable side lengths for my calculations, as if I hard code the values in the edge distance for each vertex of the triangle within the geometry shader, the teapot no longer flickers, but neither does a wireframe display. (variables ha, hb, hc in the geo shader below)
I was wondering if anyone has run into this issue before or are aware of a workaround.
Below are some sections of my code:
Geometry Shader:
/*
* Geometry Shader
*
* CSCI 499, Computer Graphics, Colorado School of Mines
*/
#version 410 core
layout( triangles ) in;
layout( triangle_strip, max_vertices = 3 ) out;
out vec3 GNormal;
out vec3 GPosition;
out vec3 ghalfwayVec;
out vec3 GLight;
noperspective out vec3 GEdgeDistance;
in vec4 TENormal[];
in vec4 TEPosition[];
in vec3 halfwayVec[];
in vec3 TELight[];
uniform mat4 ViewportMatrix;
void main() {
// Transform each vertex into viewport space
vec3 p0 = vec3(ViewportMatrix * (gl_in[0].gl_Position / gl_in[0].gl_Position.w));
vec3 p1 = vec3(ViewportMatrix * (gl_in[1].gl_Position / gl_in[1].gl_Position.w));
vec3 p2 = vec3(ViewportMatrix * (gl_in[2].gl_Position / gl_in[2].gl_Position.w));
// Find the altitudes (ha, hb and hc)
float a = length(p1 - p2);
float b = length(p2 - p0);
float c = length(p1 - p0);
float alpha = acos( (b*b + c*c - a*a) / (2.0*b*c) );
float beta = acos( (a*a + c*c - b*b) / (2.0*a*c) );
float ha = abs( c * sin( beta ) );
float hb = abs( c * sin( alpha ) );
float hc = abs( b * sin( alpha ) );
// Send the triangle along with the edge distances
GEdgeDistance = vec3( ha, 0, 0 );
GNormal = vec3(TENormal[0]);
GPosition = vec3(TEPosition[0]);
gl_Position = gl_in[0].gl_Position;
EmitVertex();
GEdgeDistance = vec3( 0, hb, 0 );
GNormal = vec3(TENormal[1]);
GPosition = vec3(TEPosition[1]);
gl_Position = gl_in[1].gl_Position;
EmitVertex();
GEdgeDistance = vec3( 0, 0, hc );
GNormal = vec3(TENormal[2]);
GPosition = vec3(TEPosition[2]);
gl_Position = gl_in[2].gl_Position;
EmitVertex();
EndPrimitive();
ghalfwayVec = halfwayVec[0];
GLight = TELight[0];
}
Fragment Shader:
/*
* Fragment Shader
*
* CSCI 441, Computer Graphics, Colorado School of Mines
*/
#version 410 core
in vec3 ghalfwayVec;
in vec3 GLight;
in vec3 GNormal;
in vec3 GPosition;
noperspective in vec3 GEdgeDistance;
layout( location = 0 ) out vec4 FragColor;
uniform vec3 mDiff, mAmb, mSpec;
uniform float shininess;
uniform light {
vec3 lAmb, lDiff, lSpec, lPos;
};
// The mesh line settings
uniform struct LineInfo {
float Width;
vec4 Color;
} Line;
vec3 phongModel( vec3 pos, vec3 norm ) {
vec3 lightVec2 = normalize(GLight);
vec3 normalVec2 = -normalize(GNormal);
vec3 halfwayVec2 = normalize(ghalfwayVec);
float sDotN = max( dot(lightVec2, normalVec2), 0.0 );
vec4 diffuse = vec4(lDiff * mDiff * sDotN, 1);
vec4 specular = vec4(0.0);
if( sDotN > 0.0 ) {
specular = vec4(lSpec * mSpec * pow( max( 0.0, dot( halfwayVec2, normalVec2 ) ), shininess ),1);
}
vec4 ambient = vec4(lAmb * mAmb, 1);
vec3 fragColorOut = vec3(diffuse + specular + ambient);
// vec4 fragColorOut = vec4(0.0,0.0,0.0,0.0);
return fragColorOut;
}
void main() {
// /*****************************************/
// /******* Final Color Calculations ********/
// /*****************************************/
// The shaded surface color.
vec4 color=vec4(phongModel(GPosition, GNormal), 1.0);
// Find the smallest distance
float d = min( GEdgeDistance.x, GEdgeDistance.y );
d = min( d, GEdgeDistance.z );
// Determine the mix factor with the line color
float mixVal = smoothstep( Line.Width - 1, Line.Width + 1, d );
// float mixVal = 1;
// Mix the surface color with the line color
FragColor = vec4(mix( Line.Color, color, mixVal ));
FragColor.a = 1;
}
I ended up stumbling across the solution to my issue. In the geometry shader, I was passing the halfway vector and the light vector after ending the primitive, as such, the values of these vectors was never being correctly sent to the fragment shader. Since no data was given to the fragment shader, garbage values were used and the Phong shading model used random values to compute the fragment color. Moving the two lines after EndPrimative() to the top of the main function in the geometry shader resolved the issue.
I'm having a problem building this on my raspberry. This same shader code works on several other computers, even if I force usage of OpenGL ES, and force the GLSL version to 1.0 es.
The #version string is added programatically to each of the shaders.
Vertex shader:
#version 100
#ifdef GL_ES
precision mediump float;
precision mediump int;
#endif
#if (__VERSION__ > 120)
#define IN in
#define OUT out
#else
#define IN attribute
#define OUT varying
#endif // __VERSION
#define MAX_LIGHTS 8
struct SLight
{
vec3 Position;
vec3 DiffuseColor;
float Intensity;
float ConstantAttenuation;
float LinearAttenuation;
float ExponentialAttenuation;
float CutoffDistance;
float CutoffIntensity;
};
struct SMaterial
{
vec3 Specular, Diffuse, Ambient;
float Shininess;
};
uniform SLight Lights[MAX_LIGHTS];
uniform int LightCount;
uniform SMaterial Material;
struct SAmbientLight
{
vec3 Color;
float Intensity;
};
uniform mat4 ModelMatrix, ViewMatrix, MVPMatrix;
uniform SAmbientLight AmbientLight;
IN vec3 VertexPosition, VertexNormal;
IN vec2 VertexTexCoord;
IN vec4 VertexColor;
OUT vec2 PerVertex_TexCoord;
OUT vec4 PerVertex_Color;
OUT vec3 PerVertex_ViewSpaceNormal, PerVertex_ViewVector;
OUT vec4 PerVertex_LightVectors[MAX_LIGHTS];
uniform bool ColoringEnabled, TexturingEnabled, LightingEnabled;
vec4 ViewSpaceLightPositions[MAX_LIGHTS];
void main()
{
mat4 ObjectToViewMatrix = ViewMatrix * ModelMatrix;
vec4 ViewSpaceCoordinate = ObjectToViewMatrix * vec4 ( VertexPosition, 1.0f );
// Calculate normal in view-space
PerVertex_ViewSpaceNormal = mat3 ( ObjectToViewMatrix ) * VertexNormal;
// Calculate light position in view-space
for ( int cont = 0; cont < LightCount; ++cont )
ViewSpaceLightPositions[cont] = ( ViewMatrix * vec4 ( Lights[cont].Position, 1.0f ) );
// Calculate vectors from the lights to this vertex
for ( int cont = 0; cont < LightCount; ++cont )
PerVertex_LightVectors[cont] = ViewSpaceLightPositions[cont] - ViewSpaceCoordinate;
// Calculate view vector
PerVertex_ViewVector = -ViewSpaceCoordinate.xyz;
gl_Position = MVPMatrix * vec4 ( VertexPosition, 1.0f );
PerVertex_TexCoord = VertexTexCoord;
if ( ColoringEnabled )
PerVertex_Color = VertexColor;
}
fragment shader:
#version 100
#ifdef GL_ES
precision mediump float;
precision mediump int;
#endif
#if (__VERSION__ > 120)
#define IN in
#else
#define IN varying
#endif // __VERSION __
#if ( __VERSION__ > 330 )
#define texture2D texture
#endif
#if ( __VERSION__ >= 300 )
#define FRAG_OUTPUT FragOutput
out vec4 FragOutput;
#else
#define FRAG_OUTPUT gl_FragColor
#endif
#define MAX_LIGHTS 8
struct SLight
{
vec3 Position;
vec3 DiffuseColor;
float Intensity;
float ConstantAttenuation;
float LinearAttenuation;
float ExponentialAttenuation;
float CutoffDistance;
float CutoffIntensity;
};
struct SMaterial
{
vec3 Specular, Diffuse, Ambient;
float Shininess;
};
uniform SLight Lights[MAX_LIGHTS];
uniform int LightCount;
uniform SMaterial Material;
struct SAmbientLight
{
vec3 Color;
float Intensity;
};
uniform mat4 ModelMatrix, ViewMatrix, MVPMatrix;
uniform SAmbientLight AmbientLight;
IN vec2 PerVertex_TexCoord;
IN vec4 PerVertex_Color;
IN vec3 PerVertex_ViewSpaceNormal, PerVertex_ViewVector;
IN vec4 PerVertex_LightVectors[MAX_LIGHTS];
uniform bool ColoringEnabled, TexturingEnabled, LightingEnabled;
uniform sampler2D TextureSampler;
vec4 CalculateLights ( void )
{
vec4 LightResult;
LightResult = vec4 ( 0.0f, 0.0f, 0.0f, 1.0f );
vec3 N = normalize ( PerVertex_ViewSpaceNormal );
vec3 V = normalize ( PerVertex_ViewVector );
for ( int cont = 0; cont < LightCount; ++cont )
{
float Distance = length ( PerVertex_LightVectors[cont] );
if ( Distance > Lights[cont].CutoffDistance )
continue;
// Normalize the incoming N, L and V vectors
vec3 L = normalize ( PerVertex_LightVectors[cont] ).xyz;
vec3 H = normalize ( L + V );
// Compute the diffuse and specular components for each fragment
vec3 diffuse = max ( dot ( N, L ), 0.0f ) * Material.Diffuse * Lights[cont].DiffuseColor /** Lights[cont].Intensity*/;
vec3 specular = pow ( max ( dot ( N, H ), 0.0f ), Material.Shininess ) * Material.Specular;
// Compute attenuation
float Attenuation = Lights[cont].ConstantAttenuation + Lights[cont].LinearAttenuation * Distance + Lights[cont].ExponentialAttenuation * pow ( Distance, 2.0f );
// Final color contribution from this light
vec3 LightContribution = vec3 ( diffuse + specular ) / Attenuation;
if ( length ( LightContribution ) < Lights[cont].CutoffIntensity )
continue;
LightResult += vec4 ( LightContribution, 1.0f );
// LightResult += vec4 ( diffuse + specular, 1.0f );
}
LightResult += vec4 ( AmbientLight.Color * AmbientLight.Intensity * Material.Ambient, 1.0f );
return LightResult;
}
void main()
{
vec4 FragmentOriginalColor;
if ( TexturingEnabled )
FragmentOriginalColor = texture2D ( TextureSampler, PerVertex_TexCoord );
else if ( ColoringEnabled )
FragmentOriginalColor = PerVertex_Color;
else
FragmentOriginalColor = vec4 ( Material.Diffuse, 1.0f );
if ( LightingEnabled )
FragmentOriginalColor *= CalculateLights();
if ( FragmentOriginalColor.a == 0.0 )
discard;
FRAG_OUTPUT = FragmentOriginalColor;
}
This is the output from my app:
DEBUG: Video driver 1: RPI
DEBUG: Video driver 2: dummy
DEBUG: Current video driver: RPI
INFO: Initializing OpenGLES2
INFO: Initializing OpenGLES2
DEBUG: Reported GL version string : OpenGL ES 2.0
DEBUG: Reported GLSL version string : OpenGL ES GLSL ES 1.00
DEBUG: Parsed GLSL version 1.0 es
glGetError 0x500
glGetError 0x500
DEBUG: OpenGL version 2.0 es
DEBUG: GLSL version 1.0 es
DEBUG: Created window 0x160a960
DEBUG: GL program info log length 9
DEBUG: vertex shader ID 1 successfully compiled
DEBUG: GL program info log length 9
DEBUG: fragment shader ID 2 successfully compiled
DEBUG: Created shader program 3
DEBUG: GL program info log length 56
ERROR: Shader program 3 link error. ERROR:LEX/PARSE-1 (vertex shader, line 61) Syntax error
Line 61 appears to be the first line inside main, where the two matrices are multiplied. What am I doing wrong?
I tried to compile the vertex shader for GLES with PVRShaderEditor (from the Power VR SDK, usefull tool to check for GLES related errors, it allows compiling shader like if you were on an iPhone).
It reports three errors:
ERROR: 0:62: 'f' : suffix for floats requires language version 300
ERROR: 0:69: 'f' : suffix for floats requires language version 300
ERROR: 0:78: 'f' : suffix for floats requires language version 300
So you just need to replace all 1.0f with 1.0 in vertex AND fragment shaders and the problem should be solved, seems like the f suffix is not supported in GLES2.0.
Note that it seems there is a bug on Pi which causes compilation errors to be shown at program linking time while they should be shown at shader compilation time... No idea why the error message you get is not more detailled ...
currently I am working on a OSG Project for my study and wrote a CelShading shader (alongside a simpleFog Shader). I first render with the CelShader along with the depth buffer to Texture and then use the fogShader. Everything works fine on my AMD Radeon HD 7950 and on my Intel HD4400 (although it is slow on the last), both running Windows. However, on a Quadro 600 runnning Linux, the Shader compiles without error, but is still wrong, the light is dulled and because of the lack of some light spots, it seems that not every light in the Scene is used. The whole toon effect is also gone.
I confirmed the Shader working on another AMD, a ATI Mobility HD3400.
But on other NVIDIAs, like a GTX 670 or 660 TI oder 560 TI (this time windows) the Shader is not working. First it was totally messed up because of non-uniform flow, but after I fixed it it is still not working.
I have this Problem now for some days and it is giving me a headache. I do not know what am I missing, why is it working on a simple Intel HD 4400 but not on high end NVIDIA Cards?
Strangely, the fogShader is working perfectly on every system and gives me the nice fog I want.
Does anyone have an idea? The Uniforms are set for the toonTex, but texture0 is not set, because the model is uv-mapped with blender, but the textures seem to work just fine (look at the Pony in the Screens). I assuming 0 is used as layout for texture0, which is perfectly valid,as far as I know. Here is a Video showing the shader on a GTX 660 TI. Something seems to work, if there is only one light, but it is not how it should look like, on a Radeon HD 7950 it is like this (ignore the black border, screenshot issue).
The light is cleary different.
EDIT: Just did another test: on the Intel HD 4400 and Windows, it is working. But the same System running Linux is showing only a whole lot of White with some outlines but no textures at all.
Anyone any suggestion?
The sources for the shaders are here:
celShader.vert
#version 120
varying vec3 normalModelView;
varying vec4 vertexModelView;
uniform bool zAnimation;
uniform float osg_FrameTime;
void main()
{
normalModelView = gl_NormalMatrix * gl_Normal;
vertexModelView = gl_ModelViewMatrix * gl_Vertex;
gl_TexCoord[0] = gl_MultiTexCoord0;
vec4 vertexPos = gl_Vertex;
if(zAnimation){//
vertexPos.z = sin(5.0*vertexPos.z + osg_FrameTime)*0.25;//+ vertexPos.z;
}
gl_Position = gl_ModelViewProjectionMatrix * vertexPos;
}
celShader.frag
#version 120
#define NUM_LIGHTS 5
uniform sampler2D texture0;
uniform sampler2D toonTex;
uniform float osg_FrameTime;
uniform bool tex;
varying vec3 normalModelView;
varying vec4 vertexModelView;
vec4 calculateLightFromLightSource(int lightIndex, bool front){
vec3 lightDir;
vec3 eye = normalize(-vertexModelView.xyz);
vec4 curLightPos = gl_LightSource[lightIndex].position;
//curLightPos.z = sin(10*osg_FrameTime)*4+curLightPos.z;
lightDir = normalize(curLightPos.xyz - vertexModelView.xyz);
float dist = distance( gl_LightSource[lightIndex].position, vertexModelView );
float attenuation = 1.0 / (gl_LightSource[lightIndex].constantAttenuation
+ gl_LightSource[lightIndex].linearAttenuation * dist
+ gl_LightSource[lightIndex].quadraticAttenuation * dist * dist);
float z = length(vertexModelView);
vec4 color;
vec3 n = normalize(normalModelView);
vec3 nBack = normalize(-normalModelView);
float intensity = dot(n,lightDir); //NdotL, Lambert
float intensityBack = dot(nBack,lightDir); //NdotL, Lambert
//-Phong Modell
vec3 reflected = normalize(reflect( -lightDir, n));
float specular = pow(max(dot(reflected, eye), 0.0), gl_FrontMaterial.shininess);
vec3 reflectedBack = normalize(reflect( -lightDir, nBack));
float specularBack = pow(max(dot(reflectedBack, eye), 0.0), gl_BackMaterial.shininess);
//Toon-Shading
//2D Toon http://www.cs.rpi.edu/~cutler/classes/advancedgraphics/S12/final_projects/hutchins_kim.pdf
vec4 toonColor = texture2D(toonTex,vec2(intensity,specular));
vec4 toonColorBack = texture2D(toonTex,vec2(intensityBack,specularBack));
if(front){
color += gl_FrontMaterial.ambient * gl_LightSource[lightIndex].ambient[lightIndex];
if(intensity > 0.0){
color += gl_FrontMaterial.diffuse * gl_LightSource[lightIndex].diffuse * intensity * attenuation ;
color += gl_FrontMaterial.specular * gl_LightSource[lightIndex].specular * specular *attenuation ;
}
return color * toonColor;
} else {//back
color += gl_BackMaterial.ambient * gl_LightSource[lightIndex].ambient[lightIndex];
if(intensity > 0.0){
color += gl_BackMaterial.diffuse * gl_LightSource[lightIndex].diffuse * intensityBack * attenuation ;
color += gl_BackMaterial.specular * gl_LightSource[lightIndex].specular * specularBack *attenuation ;
}
return color * toonColorBack;
}
}
void main(void) {
vec4 color = vec4(0.0);
bool front = true;
//non-uniform-flow error correction
//see more here: http://www.opengl.org/wiki/GLSL_Sampler#Non-uniform_flow_control
//and here: http://gamedev.stackexchange.com/questions/32543/glsl-if-else-statement-unexpected-behaviour
vec4 texColor = texture2D(texture0,gl_TexCoord[0].xy);
if(!gl_FrontFacing)
front = false;
for(int i = 0; i< NUM_LIGHTS; i++){
color += calculateLightFromLightSource(i,front);
}
if(tex)
gl_FragColor =color * texColor;
else
gl_FragColor = color;
}
fogShader.vert
#version 120
varying vec4 vertexModelView;
void main()
{
gl_Position = ftransform();
vertexModelView = gl_ModelViewMatrix * gl_Vertex;
gl_TexCoord[0] = gl_MultiTexCoord0;
}
fogShader.frag
varying vec4 vertexModelView;
uniform sampler2D texture0;
uniform sampler2D deepth;
uniform vec3 fogColor;
uniform float zNear;
uniform float zFar;
float linearDepth(float z){
return (2.0 * (zNear+zFar)) / ((zFar + zNear) - z * (zFar - zNear));// -1.0;
}
void main(void){
//Literature
//http://www.ozone3d.net/tutorials/glsl_fog/p04.php and depth_of_field example OSG Cookbook
vec2 deepthPoint = gl_TexCoord[0].xy;
float z = texture2D(deepth, deepthPoint).x;
//fogFactor = (end - z) / (end - start)
z = linearDepth(z);
float fogFactor = (4000*4-z) / (4000*4 - 30*4);
fogFactor = clamp(fogFactor, 0.0, 1.0);
vec4 texColor = texture2D(texture0,gl_TexCoord[0].xy);
gl_FragColor = mix(vec4(fogColor,1.0), texColor,fogFactor);
}
ProgramLinking
osg::ref_ptr<osg::Shader> toonFrag = osgDB::readShaderFile("../Shader/celShader.frag");
osg::ref_ptr<osg::Shader> toonVert = osgDB::readShaderFile("../Shader/" + _vertSource);
osg::ref_ptr<osg::Program> celShadingProgram = new osg::Program;
celShadingProgram->addShader(toonFrag);
celShadingProgram->addShader(toonVert);
osg::ref_ptr<osg::Texture2D> toonTex = new osg::Texture2D;
toonTex->setImage(osgDB::readImageFile("../BlenderFiles/Texturen/toons/" + _toonTex));
toonTex->setFilter(osg::Texture::MIN_FILTER, osg::Texture::NEAREST);
toonTex->setFilter(osg::Texture::MAG_FILTER, osg::Texture::NEAREST);
osg::ref_ptr<osg::StateSet> ss = new osg::StateSet;
ss->setTextureAttributeAndModes(1, toonTex, osg::StateAttribute::OVERRIDE | osg::StateAttribute::ON);
ss->addUniform(new osg::Uniform("toonTex", 1));
ss->setAttributeAndModes(celShadingProgram, osg::StateAttribute::OVERRIDE | osg::StateAttribute::ON);
//TODO NEEED?
ss->setTextureMode(1, GL_TEXTURE_1D, osg::StateAttribute::OVERRIDE | osg::StateAttribute::OFF);
ss->addUniform(new osg::Uniform("tex", true));
ss->addUniform(new osg::Uniform("zAnimation", false));
Okay, I finally found the error.
There was a faulty Line since version zero of my Shader which I overlooked for a whole week (and I am suprised my AMD Driver did not gave my an error, it was just plain wrong!
EDIT: not wrong at all, see comment below!).
This two lines were broken:
color += gl_FrontMaterial.ambient * gl_LightSource[lightIndex].ambient[lightIndex];
color += gl_BackMaterial.ambient * gl_LightSource[lightIndex].ambient[lightIndex];
ambient is of course not an array....
I've been having problems sending the shininess factor to my bump mapping shader.
The result always looks like this: http://i.imgur.com/unzdx.jpg
But if I hard code the value inside the shader to 0.0 it's working just fine.
When I send 0.0 to the shader it's turning out like in the picture above.
Any ideas?
Here's my shader
#version 110
uniform sampler2D tex;
uniform sampler2D bmap;
uniform bool boolBump;
uniform vec4 vecColor;
uniform bool onlyColor;
uniform float fTransparencyThresh;
uniform float fShininess;
uniform float alpha;
varying vec3 vecLight;
varying vec3 vecEye;
varying vec3 vecNormal;
vec4 getLighting()
{
//Ambient part
vec4 color = (gl_FrontLightModelProduct.sceneColor * gl_FrontMaterial.ambient) + (gl_LightSource[0].ambient * gl_FrontMaterial.ambient);
//For bump mapping, the normal comes from the bump map texture lookup
vec3 n = normalize(vecNormal);
if(boolBump)
{
n = normalize(texture2D(bmap, gl_TexCoord[0].st).xyz * 2.0 - 1.0);
}
vec3 l = normalize(vecLight);
//Lambert term
float NdotL = dot(n, l);
if(NdotL > 0.0)
{
//Diffuse part
color += gl_LightSource[0].diffuse * gl_FrontMaterial.diffuse * max(0.0, NdotL);
//Specular part
vec3 e = normalize(vecEye);
vec3 r = normalize(-reflect(l,n));
float spec = pow(max(0.0, dot(r, e)), fShininess);
color += gl_LightSource[0].specular * gl_FrontMaterial.specular * spec;
}
return color;
}
void main(void)
{
vec4 texel = texture2D(tex, gl_TexCoord[0].st);
if(texel.a < fTransparencyThresh)
discard;
//Get shading
vec4 color = getLighting();
//Color only mode?
if(onlyColor)
{
color *= vecColor;
}
else
{
color *= texel;
}
//Set fragment color, alpha comes from MTL file
gl_FragColor = vec4(color.xyz, alpha);
}
Edit, OpenGL code:
void MyClass::sendToShader(const OBJ::StelModel* pStelModel, Effect cur, bool& tangEnabled, int& tangLocation)
{
int location;
tangEnabled = false;
if(cur != No)
{
location = curShader->uniformLocation("fTransparencyThresh");
curShader->setUniform(location, fTransparencyThresh);
location = curShader->uniformLocation("alpha");
curShader->setUniform(location, pStelModel->pMaterial->alpha);
location = curShader->uniformLocation("fShininess");
curShader->setUniform(location, 0.0f);
...
Edit: Even this wont work:
GLint loc = glGetUniformLocation(curShader->program, "fShininess");
glUniform1f(loc, 0.0f);
Note that pow(0, 0) is undefined. This means spec is undefined if dot(r, e) == 0 and fShininess == 0.
Do you make sure the program is actively bound when you call glUniform? Do you check glGetError anywhere?