When I try adding a geometry shader between working vertex and fragment shaders I get a link error:
Fragment shader(s) failed to link, vertex shader(s) failed to link.
ERROR: error(#280) Not all shaders have valid object code
ERROR: error(#280) Not all shaders have valid object code
All three shaders compile without errors. I guess the in and outs doesn't fit in the information flow pipeline. The built-in ins and outs confuse me so I can't spot the error.
Source for the shaders:
vertex_source =
"#version 330\n"
"in vec3 Position;\n"
"in vec2 TexCoord;\n"
"out vec3 oColor;\n"
"out vec2 oTexcoord;\n"
"void main() {\n"
" oTexcoord = TexCoord;\n"
" gl_Position = gl_ModelViewProjectionMatrix*vec4(Position, 1.0);\n"
"}\n";
geometry_source =
"#version 330\n";
"layout (triangles) in;\n";
"layout (triangle_strip, max_vertices=3) out;\n";
"in vec3 Color;\n";
"in vec2 TexCoord;\n";
"out vec3 oColor;\n";
"out vec2 oTexCoord;\n";
"void main() {\n";
" oColor = Color;\n";
" oTexCoord = TexCoord;\n";
" gl_Position = gl_in[0].gl_Position;\n";
" EmitVertex();\n";
" gl_Position = gl_in[1].gl_Position;\n";
" EmitVertex();\n";
" gl_Position = gl_in[2].gl_Position;\n";
" EmitVertex();\n";
" EndPrimitive();\n";
"}\n";
fragment_source =
"#version 330\n"
"in vec2 oTexcoord;\n"
"out vec4 oColor;\n"
"uniform sampler2D tex;\n"
"uniform sampler2D tex_norm;\n"
"uniform sampler2D tex_spec;\n"
"void main() {\n"
" vec4 lightpos = normalize(-gl_ModelViewProjectionMatrix*vec4(1.0, -1.0, -1.5, 1.0));\n"
" vec3 tmpNorm = normalize(texture2D(tex_norm, oTexcoord).rgb * 2.0 - 1.0);\n"
" float a = dot(tmpNorm, lightpos.xyz);\n"
" float difuse = max(a, 0.1);\n"
" float spec = texture2D(tex_spec, oTexcoord).r * pow(a, 2.0);\n"
" vec3 tmpcolor = difuse * texture2D(tex, oTexcoord).rgb;\n"
" oColor = vec4(tmpcolor+tmpcolor*spec, 1.0);\n"
"}\n";
What am I doing wrong in the geometry shader?
I have tried skipping the unused oColor out and changed to an array in geometry shader like this:
#define GLSL(src) "#version 330 core\n" #src
vertex_source = GLSL(
in vec3 Position;
in vec2 TexCoord;
out vec2 oTexcoord;
void main() {
gl_Position = gl_ModelViewProjectionMatrix*vec4(Position, 1.0);
oTexcoord = TexCoord;
}
);
geometry_source = GLSL(
layout (triangles) in;
layout (triangle_strip, max_vertices=3) out;
in vec2 gsTexCoord[];
out vec2 gsoTexCoord;
void main() {
gsoTexCoord = gsTexCoord[0];
gl_Position = gl_in[0].gl_Position;
EmitVertex();
gsoTexCoord = gsTexCoord[1];
gl_Position = gl_in[1].gl_Position;
EmitVertex();
gsoTexCoord = gsTexCoord[2];
gl_Position = gl_in[2].gl_Position;
EmitVertex();
EndPrimitive();
}
);
fragment_source = GLSL(
in vec2 oTexcoord;
out vec4 oColor;
uniform sampler2D tex;
uniform sampler2D tex_norm;
uniform sampler2D tex_spec;
void main() {
vec4 lightpos = normalize(-gl_ModelViewProjectionMatrix*vec4(1.0, -1.0, -1.5, 1.0));
vec3 tmpNorm = normalize(texture2D(tex_norm, oTexcoord).rgb * 2.0 - 1.0);
float a = dot(tmpNorm, lightpos.xyz);
float difuse = max(a, 0.1);
float spec = texture2D(tex_spec, oTexcoord).r * pow(a, 2.0);
vec3 tmpcolor = difuse * texture2D(tex, oTexcoord).rgb;
oColor = vec4(tmpcolor+tmpcolor*spec, 1.0);
}
);
That gives me the following link error:
Fragment shader(s) failed to link, vertex shader(s) failed to link.
ERROR: error(#277) Symbol 'gsTexCoord[0]' usage doesn't match between two stages
ERROR: error(#277) Symbol 'oTexcoord' usage doesn't match between two stages
ERROR: error(#277) Symbol 'gsTexCoord[0]' usage doesn't match between two stages
ERROR: error(#277) Symbol 'oTexcoord' usage doesn't match between two stages
Your geometry shader inputs need to be array-valued and match the names in your vertex shader:
// existing vertex shader outputs:
out vec3 oColor;
out vec2 oTexcoord;
// wrong geometry shader inputs:
in vec3 Color;
in vec2 TexCoord;
// correct geometry shader inputs:
in vec3 oColor[];
in vec2 oTexCoord[];
Related
I have a vertex shader that takes in position, texture coordinates, normals and some uniforms:
#version 330 core
layout(location = 0) in vec4 position;
layout(location = 1) in vec2 texCoord;
layout(location = 2) in vec3 normal;
//MVP
uniform mat4 u_Model;
uniform mat4 u_View;
uniform mat4 u_Proj;
//Lighting
uniform mat4 u_InvTranspModel;
uniform mat4 u_LightMVP;
out DATA
{
vec2 v_TexCoord;
vec3 v_Normal;
vec3 v_FragPos;
vec4 v_LightSpacePos;
mat4 v_Proj;
} data_out[];
void main()
{
gl_Position = u_Model * position;
data_out.v_TexCoord = texCoord;
data_out.v_Normal = mat3(u_InvTranspModel) * normal;
data_out.v_Proj = u_Proj * u_View * u_Model;
//Light
data_out.v_FragPos = vec3(u_Model*position);
data_out.v_LightSpacePos = u_LightMVP * position;
}
I'm passing into my geometry shader:
#version 330 core
layout(triangles) in;
layout(triangle_strip, max_vertices = 3) out;
in DATA
{
vec2 v_TexCoord;
vec3 v_Normal;
vec3 v_FragPos;
vec4 v_LightSpacePos;
mat4 v_Proj;
} data_in[];
out vec2 g_TexCoord;
out vec3 g_Normal;
out vec3 g_FragPos;
out vec4 g_LightSpacePos;
void main()
{
gl_Position = data_in[0].v_Proj * gl_in[0].gl_Position;
g_Normal = data_in[0].v_Normal;
g_FragPos = data_in[0].v_FragPos;
g_TexCoord = data_in[0].v_TexCoord;
g_LightSpacePos = data_in[0].v_LightSpacePos;
EmitVertex();
gl_Position = data_in[1].v_Proj * gl_in[1].gl_Position;
g_Normal = data_in[1].v_Normal;
g_FragPos = data_in[1].v_FragPos;
g_TexCoord = data_in[1].v_TexCoord;
g_LightSpacePos = data_in[1].v_LightSpacePos;
EmitVertex();
gl_Position = data_in[2].v_Proj * gl_in[2].gl_Position;
g_Normal = data_in[2].v_Normal;
g_FragPos = data_in[2].v_FragPos;
g_TexCoord = data_in[2].v_TexCoord;
g_LightSpacePos = data_in[2].v_LightSpacePos;
EmitVertex();
EndPrimitive();
}
However I get the errors:
ERROR: 0:28: '.' : dot operator to an array only takes length()
ERROR: 0:28: 'assign' : cannot convert from 'attribute 2-component vector of highp float' to 'varying unknown-sized array of highp block'
ERROR: 0:29: '.' : dot operator to an array only takes length()
ERROR: 0:29: 'assign' : cannot convert from '3-component vector of highp float' to 'varying unknown-sized array of highp block'
................ Etc
I get these errors for every variable in the vertex shader that is passed to the geometry shader.
This shader works when its in a form without geometry shader, and should be setup currently to do nothing, so what have I done wrong?
The output of the vertex shader is not an array, even if the next stage is a Geometry shader. The Vertex shader processes a single vertex, and therefore the outputs are always single values related to that vertex. The geometry shader's input interface is an array because the geometry shader takes a primitive (multiple vertices) as input rather than a single vertex. Remove [] in the vertex shader:
out DATA
{
vec2 v_TexCoord;
vec3 v_Normal;
vec3 v_FragPos;
vec4 v_LightSpacePos;
mat4 v_Proj;
} data_out; // <--- remove []
I am using QOpenGLWidget to render some CAD meshes. I started with an example that had the shader source code written directly into the code in the following way:
Vertex shader
static const char *vertexShaderSourceCore =
"#version 330\n"
"in vec4 vertex;\n"
"in vec3 normal;\n"
"out vec3 vert;\n"
"out vec3 vertNormal;\n"
"uniform mat4 projMatrix;\n"
"uniform mat4 mvMatrix;\n"
"uniform mat3 normalMatrix;\n"
"void main() {\n"
" vert = vertex.xyz;\n"
" vertNormal = normalMatrix * normal;\n"
" gl_Position = projMatrix * mvMatrix * vertex;\n"
"}\n";
Fragment shader
static const char *fragmentShaderSourceCore =
"#version 330\n"
"in highp vec3 vert;\n"
"in highp vec3 vertNormal;\n"
"out highp vec4 fragColor;\n"
"uniform highp vec3 lightPos;\n"
"void main() {\n"
" highp vec3 L = normalize(lightPos - vert);\n"
" highp float NL = max(dot(normalize(vertNormal), L), 0.0);\n"
" highp vec3 color = vec3(0.39, 0.4, 0.0);\n"
" highp vec3 col = clamp(color * 0.2 + color * 0.8 * NL, 0.0, 1.0);\n"
" fragColor = vec4(col, 1.0);\n"
"}\n";
I load this code into my QOpenGLShaderProgram with the function addShaderFromSourceCode. With this, everything works as expected.
Now I wanted to move the shader source code to a separate file in order to make the code cleaner. I created a .qrc file and put in the shaders in the following way:
Vertex Shader
#version 330
in vec4 vertex;
in vec3 normal;
out vec3 vert;
out vec3 vertNormal;
uniform mat4 projMatrix;
uniform mat4 mvMatrix;
uniform mat3 normalMatrix;
void main()
{
vert = vertex.xyz;
vertNormal = normalMatrix * normal;
gl_Position = projMatrix * mvMatrix * vertex;
}
Fragment shader
in highp vec3 vert;
in highp vec3 vertNormal;
out highp vec4 fragColor;
uniform highp vec3 lightPos;
void main() {
highp vec3 L = normalize(lightPos - vert);
highp float NL = max(dot(normalize(vertNormal), L), 0.0);
highp vec3 color = vec3(0.39, 0.4, 0.0);
highp vec3 col = clamp(color * 0.2 + color * 0.8 * NL, 0.0, 1.0);
fragColor = vec4(col, 1.0);
}
I then wanted to use QOpenGLShaderProgram::addShaderFromSourceFile to load the shader code from these files.
The vertex shader loads without issues, but when importing the fragment shader I get the following error message:
QOpenGLShader::compile(Fragment): ERROR: 4:1: ':' : syntax error syntax error
*** Problematic Fragment shader source code ***
#version 110
#ifdef GL_KHR_blend_equation_advanced
#extension GL_ARB_fragment_coord_conventions : enable
#extension GL_KHR_blend_equation_advanced : enable
#endif
#define lowp
#define mediump
#define highp
#line 1
:/globalCore.frag
***
which I do not understand. I don't think its a compatibility issue since I have two additional shaders if core mode is not enabled.
Can someone help me understand where this ominous "syntax error" is coming from? I don't have a colon in my shader code so I am at a loss here.
I have a single VBO with the following vertex attributes:
3 floats for x,y,z
3 floats for r,g,b
2 floats for velocity_x,velocity_y
I'd like to apply the velocity of a given vertex to its position, in the vertex shader and have done this so far, but it doesn't seem to be applying any changes:
"#version 330 core\n"
"layout (location = 0) in vec3 vertexPos;\n"
"layout (location = 1) in vec3 vertexColor;\n"
"layout (location = 2) in vec2 vertexVelocity;\n"
"vec3 newPosition;\n"
"out vec3 vertexColorRes;\n"
"uniform mat4 viewMatrix;\n"
"uniform mat4 projectionMatrix;\n"
"void main()\n"
"{\n"
" newPosition = vertexPos + vec3(vertexVelocity, 1.0);\n"
" gl_Position = projectionMatrix * viewMatrix * vec4(newPosition, 1.0);\n"
" vertexColorRes = vertexColor;\n"
"}\0"));
What seems to be the problem?
I want to porting demo project of Box2D from VS2013 in Qt. But i have one unusual problem. When i run demo project in VS i get message with info about my openGL configuration.
I replaced code on Qt and changed initialization of shaders and calls of opengl funcitons with QOpeGL wrappers.
Firstly, i change default surface format like this:
QSurfaceFormat format;
format.setVersion(3, 1);
format.setProfile(QSurfaceFormat::CoreProfile);
QSurfaceFormat::setDefaultFormat(format);
But when i debug program is format of my surface stay on 3.0.
And when i try to create shaders i get error message like this:
QOpenGLShader::compile(Vertex): ERROR: 0:1: '140' : version number not supported
ERROR: 0:2: 'layout' : syntax error
*** Problematic Vertex shader source code ***
#version 140
#line 1
uniform mat4 projectionMatrix;
layout(location = 0) in vec2 v_position;
layout(location = 1) in vec4 v_color;
layout(location = 2) in float v_size;
out vec4 f_color;
void main(void)
{
f_color = v_color;
gl_Position = projectionMatrix * vec4(v_position, 0.0f, 1.0f);
gl_PointSize = v_size;
}
Why VS can create shaders and work with OpenGL 3.1/GLSL 1.40, but Qt doesn't do this?
Initialize of GL (m_functions - QOpenGLExtraFunctions)
void MainOpenGLWidget::initializeGL()
{
makeCurrent();
qDebug() << "OPENGL " << QSurfaceFormat::defaultFormat().majorVersion() <<
"." << QSurfaceFormat::defaultFormat().minorVersion();
m_functions.initializeOpenGLFunctions();
m_functions.glClearColor(0, 0, 0, 0);
g_camera.m_width = 1024;
g_camera.m_height = 640;
g_debugDraw.Create(&m_functions);
}
function g_debugDraw.Create(...):
void Create(QOpenGLExtraFunctions *functions)
{
const char *vs = \
"#version 140\n"
"uniform mat4 projectionMatrix;\n"
"layout(location = 0) in vec2 v_position;\n"
"layout(location = 1) in vec4 v_color;\n"
"layout(location = 2) in float v_size;\n"
"out vec4 f_color;\n"
"void main(void)\n"
"{\n"
" f_color = v_color;\n"
" gl_Position = projectionMatrix * vec4(v_position, 0.0f, 1.0f);\n"
" gl_PointSize = v_size;\n"
"}\n";
...
m_program.addShaderFromSourceCode(QOpenGLShader::Vertex, vs);
...
m_functions = *functions;
m_functions.glGenVertexArrays(1, &m_vaoId);
m_functions.glGenBuffers(3, m_vboIds);
m_functions.glBindVertexArray(m_vaoId);
m_functions.glEnableVertexAttribArray(m_vertexAttribute);
m_functions.glEnableVertexAttribArray(m_colorAttribute);
m_functions.glEnableVertexAttribArray(m_sizeAttribute);
...
}
I get error when call m_program.addShaderFromSourceCode(QOpenGLShader::Vertex, vs);
If you really want to stick to GLSL #version 140, then replace the following lines
layout(location = 0) in vec2 v_position;
layout(location = 1) in vec4 v_color;
layout(location = 2) in float v_size;
by
in vec2 v_position;
in vec4 v_color;
in float v_size;
Explicit attribute location is not part of GLSL until #version 330.
Be careful after that to query your shader's attribute location before enabling it in your C++ code. The shader compiler may or may not order them in the order of declaration.
const int POS_LOCATION = glGetAttribLocation(program_id, "v_position");
if(-1 != POS_LOCATION)
{
glEnableVertexAttribArray(POS_LOCATION);
...
glVertexAttribPointer(POS_LOCATION, ... );
...
}
I've found no mention of layout(location = x) in documentation of GLSL #version 140.
https://www.khronos.org/registry/OpenGL/specs/gl/GLSLangSpec.1.40.pdf
Not mentioned until #version 330 at page 35.
https://www.khronos.org/registry/OpenGL/specs/gl/GLSLangSpec.3.30.pdf
In your case the shader compiler error message is a little misleading. Maybe if you update you graphic card driver you'll get a better shader compiler.
I didn't took into account that GLSL for desktop is not the same that GLSL from OpenGL ES. This topic little helped me. I change all in to attribute or varying and all out to varying and also set precision on float. After change my shader was compile. Finally my shader code looks like this:
precision lowp float;
uniform mat4 projectionMatrix;
attribute vec2 v_position;
attribute vec4 v_color;
attribute float v_size;
varying vec4 f_color;
void main(void)
{
f_color = v_color;
gl_Position = projectionMatrix * vec4(v_position, 0.0, 1.0);
gl_PointSize = v_size;
}
Thank Octo for support!
I'm trying to calculate per-face normals in geometry shader, using the following pipeline
//VERTEX_SHADER
#version 330
layout(location = 0) in vec4 vertex;
out vec3 vert;
uniform mat4 projMatrix;
uniform mat4 mvMatrix;
void main()
{
vert = vertex.xyz;
gl_Position = projMatrix * mvMatrix * vertex;
}
//GEOMETRY_SHADER
#version 330
layout ( triangles ) in;
layout ( triangle_strip, max_vertices = 3 ) out;
out vec3 normal_out;
uniform mat3 normalMatrix;
void main()
{
vec3 A = gl_in[2].gl_Position.xyz - gl_in[0].gl_Position.xyz;
vec3 B = gl_in[1].gl_Position.xyz - gl_in[0].gl_Position.xyz;
normal_out = normalMatrix * normalize(cross(A,B));
gl_Position = gl_in[0].gl_Position;
EmitVertex();
gl_Position = gl_in[1].gl_Position;
EmitVertex();
gl_Position = gl_in[2].gl_Position;
EmitVertex();
EndPrimitive();
}
//FRAG_SHADER
#version 330
in vec3 normal_out;
in vec3 vert;
out vec4 fColor;
uniform vec3 lightPos;
void main()
{
highp vec3 L = normalize(lightPos - vert);
highp float NL = max(dot(normal_out, L), 0.0);
highp vec3 color = vec3(1, 1, 0.0);
fColor = vec4(color*NL, 1.0);
}
However, I end up with very weird looking faces that keeps flickering(I included a snapshot below). It occurred to me that it might be because I'm using 8 vertices to represent 1 cell(cube) instead of 24 vertices, But I'm not quite sure if that is what is causing the problem.
Left: Using Light Weighting 'NL', Right:Without
After every call to EmitVertex, the contents of all output variables are made undefined. Therefore, if you want to output the same value to multiple vertices, you must copy it to the output every time.
Also, note that each shader stage's outputs provide inputs only to the next stage. So if you have a GS, and you want to pass a value from the VS to the FS, you must have the GS explicitly pass that value through.