GLSL shader wont compile, can someone help me find out why? - c++

I've been staring at this for too long and I'm too new to GLSL to know what is wrong. All I know is that when checking to see if the vertex shader compiles, it says that it could not do so. If someone could help me find out what I've done wrong that would be amazing.
textureShader.vert
#version 140
uniform mat4 mvpMatrix;
attribute vec3 position;
attribute vec2 textCoord;
varying vec2 TextCoord;
varying vec3 lightDir,normal;
void main()
{
normal = normalize(gl_NormalMatrix * gl_Normal);
lightDir = normalize(vec3(gl_LightSource[0].position));
gl_TexCoord[0] = gl_MultiTexCoord0;
gl_Position = position;
}
textureShader.frag
#version 140
uniform sampler2D texUnit;
varying vec2 TextCoord;
varying vec3 lightDir,normal;
void main()
{
vec3 ct,cf;
vec4 texel;
float intensity,at,af;
intensity = max(dot(lightDir,normalize(normal)),0.0);
cf = intensity * (gl_FrontMaterial.diffuse).rgb + gl_FrontMaterial.ambient.rgb;
af = gl_FrontMaterial.diffuse.a;
texel = texture2D(texUnit, TextCoord);
ct = texel.rgb;
at = texel.a;
gl_FragColor = vec4(ct * cf, at * af);
}
What I'm doing to check the compilation. DBOUT is a function to write to the Visual Studio output box.
glCompileShader(shader_vp);
validateShader(shader_vp, vsFile);
GLint compiled;
glGetShaderiv(shader_vp, GL_COMPILE_STATUS, &compiled);
if (!compiled){
DBOUT("Couldn't Compile Vertex Shader: Aborting Mission\n");
abort();
}
glCompileShader(shader_fp);
validateShader(shader_fp, fsFile);
glGetShaderiv(shader_fp, GL_COMPILE_STATUS, &compiled);
if (!compiled){
DBOUT("Couldn't Compile Fragment Shader: Aborting Mission\n");
abort();
}
The output I receive:
Couldn't Compile Vertex Shader: Aborting Mission
Debug Error!
SOLVED
So with everyones help I go this to compile. I had to replace these lines:
gl_TexCoord[0] = gl_MultiTexCoord0;
gl_Position = position;
With these ones:
TextCoord = vec2(textCoord);
gl_Position = mvpMatrix * vec4(position,1.0f);
Thank you everyone!

I didn't look at your shader but you can get an error message from the compiler with something like:
auto error = GLint();
::glGetShaderiv(id, GL_COMPILE_STATUS, &error);
if(error != GL_TRUE)
{
auto length = GLint();
::glGetShaderiv(id, GL_INFO_LOG_LENGTH, &length);
if(length > 0)
{
auto log = std::vector<GLchar>(length, 0);
::glGetShaderInfoLog(id, length, nullptr, &log[0]);
auto message = std::string(log.begin(), log.end());
...
}
}

One possible error in the shader might be:
gl_Position = position;
The gl_Position should be of type vec4, but the position is an attribute of vec3, you probably forgot to do something like:
gl_Position = mvpMatrix * vec4(position, 1.0f);

Related

Cant enable GLSL 1.40 in my Qt application

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!

Light with vertex/fragment shader. Using varying variables. (openGL)

I was looking for a lot of this problem. I found this question Passing data into different shaders but this problem not mine. I get "The fragment shader uses varying "normal", but previous shader does not write to it." error message.
My vertey shader code:
#version 430
in layout(location=0) vec3 position;
in layout(location=1) vec3 normal;
out vec3 norm;
uniform mat4 transformation;
void main()
{
gl_Position = transformation * vec4(position, 1.0);
norm = (transformation * vec4(normal, 0.0)).xyz;
}
And my fragment shader code:
#version 430
in vec3 normal;
out vec4 colour;
vec3 lightPos = vec3(0,50,0);
vec3 lightColor = vec3(0.5, 0, 0);
vec3 materialColor = vec3(0, 1.0, 0);
void main() {
float cosTheta = dot(-lightPos, normalize(normal));
vec3 temp = materialColor * lightColor * cosTheta;
colour = vec4(temp, 1.0);
}
What is the main problem? I don't understand this message my vertex shader using the normal vector and it passing into fragment shader. I don't see difference between the linked code and mine. Please tell me some idea :\
If you want to use different variable names for some reason you can specify a location to match in- and output variables.
For example, in your case:
.vert:
out layout(location = 7) vec3 norm;
.frag:
in layout(location = 7)vec3 normal;

Calculating Per face normals in Geometry Shader

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.

Shader creation Opengl

I am using OpenGl 3 and the tutorial from BennyBox on Youtube.
Using this method:
static void CheckShaderError(GLuint shader, GLuint flag, bool isProgram, const std::string& errorMessage){
GLint success = 0;
GLchar error [1024] = {0};
if(isProgram){
glGetProgramiv(shader, flag, &success);
}else{
glGetShaderiv(shader, flag, &success);
}
if(success == GL_FALSE){
if(isProgram){
glGetProgramInfoLog(shader, sizeof(error), NULL, error);
}else{
glGetShaderInfoLog(shader,sizeof(error), NULL, error);
}
std::cerr<< errorMessage<< ": " << error<< "'"<<std::endl;
}
}
I should be able to load shader file (fragment and vertex shaders). It works with basic shaders but when I try to modify them to that point:
#version 120
attribute vec3 position;
attribute vec2 texCoord;
varying vec2 texCoord;
void main(){
gl_Position = vec4(position, 1.0);
texCoord0 = texCoord;
}
The I get:
Error compiling shader!: 'ERROR: 0:6: 'texCoord' : redefinition
ERROR: 0:11: 'texCoord0' : undeclared identifier
ERROR: 0:11: 'assign' : cannot convert from 'attribute 2-component vector of float' to 'float'
and the fragment shader:
#version 120
uniform sampler2D diffuse;
varying vec2 texCoord0;
void main(){
gl_FragColor = texture2D(diffuse, texCoord0);
}
gives:
Unable to load shader: ./res/basicShader.fs
Error linking shader program: 'Attached vertex shader is not compiled.
I have the exact same code as the video, and it runs fine using basic coloring shader. I am on Visual Studio 2012.
There are two errors in your vertex shader.
First, you are declaring texCoord twice.
attribute vec2 texCoord;
varying vec2 texCoord;
Then you are trying to use a varying called texCoord0, without ever declaring it.
texCoord0 = texCoord;
Your vertex shader should look like this:
#version 120
attribute vec3 position;
attribute vec2 texCoord;
varying vec2 texCoord0;
void main(){
gl_Position = vec4(position, 1.0);
texCoord0 = texCoord;
}

Linking error at tessellation shaders in GLSL

I'm testing the triangle tessellation from the link http://prideout.net/blog/?p=48#shaders. All the shader are compiled correctly, but when I try to link the program using the command:
glLinkProgram(programID);
I got the following error:
Tessellation control info
(0): error C6029: No input primitive type
----------------------------------------
Tessellation evaluation info
(0): error c7005: No tessellation primitive mode specified
-----------------------------------------------------------
Geometry info
(0): error C6022: No input primitive type
(0): error C6029: No ouput primitive type
----------------------------------------
Not valid
It's so strange I declare output for TC Shader using command:
layout(vertices = 3) out;
And input layout for TE shader using command:
layout(triangles, equal_spacing, cw) in;
Why I still got this error?
I hope to see you answer about it.
I put my shaders in below:
Vertex shader:
#version 410 core
in vec4 Position;
out vec3 vPosition;
void main()
{
vPosition = Position.xyz;
}
TC shader:
#version 410 core
layout(vertices = 3) out;
in vec3 vPosition[];
out vec3 tcPosition[];
#define ID gl_InvocationID
void main()
{
float TessLevelInner = 3;
float TessLevelOuter = 2;
tcPosition[ID] = vPosition[ID];
if (ID == 0) {
gl_TessLevelInner[0] = TessLevelInner;
gl_TessLevelOuter[0] = TessLevelOuter;
gl_TessLevelOuter[1] = TessLevelOuter;
gl_TessLevelOuter[2] = TessLevelOuter;
}
}
TE Shader:
#version 410 core
//TessEval
layout(triangles, equal_spacing, cw) in;
in vec3 tcPosition[];
out vec3 tePosition;
out vec3 tePatchDistance;
uniform mat4 Projection;
uniform mat4 Modelview;
void main()
{
vec3 p0 = gl_TessCoord.x * tcPosition[0];
vec3 p1 = gl_TessCoord.y * tcPosition[1];
vec3 p2 = gl_TessCoord.z * tcPosition[2];
tePatchDistance = gl_TessCoord;
tePosition = normalize(p0 + p1 + p2);
gl_Position = Projection * Modelview * vec4(tePosition, 1);
}
Geometry shader:
#version 410 core
//geometry shader
layout(triangles) in;
layout(triangle_strip, max_vertices = 3) out;
in vec3 tePosition[3];
in vec3 tePatchDistance[3];
out vec3 gFacetNormal;
out vec3 gPatchDistance;
out vec3 gTriDistance;
uniform mat4 Modelview;
uniform mat3 NormalMatrix;
void main()
{
vec3 A = tePosition[2] - tePosition[0];
vec3 B = tePosition[1] - tePosition[0];
gFacetNormal = NormalMatrix * normalize(cross(A, B));
gPatchDistance = tePatchDistance[0];
gTriDistance = vec3(1, 0, 0);
gl_Position = gl_in[0].gl_Position; EmitVertex();
gPatchDistance = tePatchDistance[1];
gTriDistance = vec3(0, 1, 0);
gl_Position = gl_in[1].gl_Position; EmitVertex();
gPatchDistance = tePatchDistance[2];
gTriDistance = vec3(0, 0, 1);
gl_Position = gl_in[2].gl_Position; EmitVertex();
EndPrimitive();
}
Fragment Shader:
#version 410 core
//fragment shader
out vec4 FragColor;
in vec3 gFacetNormal;
in vec3 gTriDistance;
in vec3 gPatchDistance;
in float gPrimitive;
uniform vec3 LightPosition;
float amplify(float d, float scale, float offset)
{
d = scale * d + offset;
d = clamp(d, 0, 1);
d = 1 - exp2(-2*d*d);
return d;
}
void main()
{
vec3 AmbientMaterial = vec3(0.04f, 0.04f, 0.04f);
vec3 DiffuseMaterial = vec3(0, 0.75, 0.75);
vec3 LightPosition = vec3(0.25, 0.25, 1);
vec3 N = normalize(gFacetNormal);
vec3 L = LightPosition;
float df = abs(dot(N, L));
vec3 color = AmbientMaterial + df * DiffuseMaterial;
float d1 = min(min(gTriDistance.x, gTriDistance.y), gTriDistance.z);
float d2 = min(min(gPatchDistance.x, gPatchDistance.y), gPatchDistance.z);
color = amplify(d1, 40, -0.5) * amplify(d2, 60, -0.5) * color;
FragColor = vec4(color, 1.0);
}
FINALLY, this is the code I set up shader sources:
std::string filename = "shaders//terrain//terrain_TCShader.glsl"
FILE* fp = fopen(fileName.c_str(), "rt");
if (!fp)
return;
// Get all lines from a file
vector<string> sLines;
char sLine[255];
while (fgets(sLine, 255, fp))
sLines.push_back(sLine);
fclose(fp);
const char** sProgram = new const char*[sLines.size()];
for (int i = 0; i < sLines.size(); i++){
sProgram[i] = sLines[i].c_str();
}
//Also for GL_TESS_EVALUATION_SHADER, ..VERTEX, ...FRAGMENT
pShader[st] = glCreateShader(GL_TESS_CONTROL_SHADER);
glShaderSource(pShader[st], 1, (const GLchar**)sProgram, NULL);
glAttachShader(pProgram, pShader[st]);
glCompileShader(pShader[st]);
//==> I tried to check error here but it's ok, the compiler do not notify anything
After compile all the shader, I link the program
glLinkProgram(pProgram);
//And check error again:
glGetProgramiv(pProgram, GL_INFO_LOG_LENGTH,&infologLength);
if (infologLength > 0)
{
infoLog = (char *)malloc(infologLength);
glGetProgramInfoLog(pProgram, infologLength, &charsWritten, infoLog);
}
//I got the error here, as I described above.
I solved the problem. The error is in the code of loading shader.
glShaderSource(pShader[st], 1, (const GLchar**)sProgram, NULL);
I changed 1 to size of the char* array sProgram