So I have been creating a game and I want to support opengl version 2.1 with shaders. I implemented what I could according to tutorials online and when I run the game nothing shows up, Note: If the shaders are changed to the latest version I support everything works fine.. (I use VBOs)
Here are the shaders:
Fragment shader:
uniform sampler2D texture1;
varying vec4 pass_Color;
varying vec2 pass_TextureCoord;
void main(void) {
gl_FragColor = pass_Color;
vec2 texcoord = vec2(pass_TextureCoord.xy);
vec4 color = texture2D(texture1, texcoord) * pass_Color ;
gl_FragColor = color;
}
*Vertex shader: *
attribute vec4 in_Position;
attribute vec4 in_Color;
attribute vec2 in_TextureCoord;
varying vec4 pass_Color;
varying vec2 pass_TextureCoord;
uniform vec4 cameraPos;
uniform mat4 projection;
void main(void) {
gl_Position = ( (vec4(cameraPos.x*projection[0][0],cameraPos.y*projection[1][1],cameraPos.z*projection[0][0],cameraPos.w*projection[0][0])) + (in_Position * projection)) ;
pass_Color = in_Color;
pass_TextureCoord = in_TextureCoord;
}
Note: In the vertex shader I calculate the position, this is correct for sure because I use this exact line to calculate position in the newer shader and it works great.
How I create the VBOs:
vboId = GL15.glGenBuffers();
GL15.glBindBuffer(GL15.GL_ARRAY_BUFFER, vboId);
GL15.glBufferData(GL15.GL_ARRAY_BUFFER, vboData, GL15.GL_STATIC_DRAW);
// Put the position coordinates in attribute list 0
GL20.glVertexAttribPointer(GL20.glGetAttribLocation(game.getResourceManager().getShaderProgramID(), "in_Position"), TexturedVertex.positionElementCount, GL11.GL_FLOAT,
false, TexturedVertex.stride, TexturedVertex.positionByteOffset);
// Put the color components in attribute list 1
GL20.glVertexAttribPointer(GL20.glGetAttribLocation(game.getResourceManager().getShaderProgramID(), "in_Color"), TexturedVertex.colorElementCount, GL11.GL_FLOAT,
false, TexturedVertex.stride, TexturedVertex.colorByteOffset);
// Put the texture coordinates in attribute list 2
GL20.glVertexAttribPointer(GL20.glGetAttribLocation(game.getResourceManager().getShaderProgramID(), "in_TextureCoord"), TexturedVertex.textureElementCount, GL11.GL_FLOAT,
false, TexturedVertex.stride, TexturedVertex.textureByteOffset);
GL15.glBindBuffer(GL15.GL_ARRAY_BUFFER, 0);
This is how I render: (Left out useless things)
GL20.glUseProgram(game.getResourceManager().getShaderProgramID());
//Send the camera location and the projection matrix
int loc3 = GL20.glGetUniformLocation(game.getResourceManager().getShaderProgramID(), "projection");
FloatBuffer buf2 = BufferUtils.createFloatBuffer(16);
GL11.glGetFloat(GL11.GL_PROJECTION_MATRIX,buf2);
GL20.glUniformMatrix4(loc3,false,buf2);
int loc4 = GL20.glGetUniformLocation(game.getResourceManager().getShaderProgramID(), "cameraPos");
GL20.glUniform4f(loc4, game.getGameCamera().getCameraLocation().x*-1*Constants.PHYS_PIXEL_TO_METER_RATIO, game.getGameCamera().getCameraLocation().y*-1*Constants.PHYS_PIXEL_TO_METER_RATIO, 0,1);
////////////////////////////RENDERING\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
GL11.glBindTexture(GL11.GL_TEXTURE_2D, textureID);
GL20.glEnableVertexAttribArray(0);
GL20.glEnableVertexAttribArray(1);
GL20.glEnableVertexAttribArray(2);
// Bind to the index VBO that has all the information about the order of the vertices
GL15.glBindBuffer(GL15.GL_ELEMENT_ARRAY_BUFFER, VBOIndeciesID);
// Draw the vertices
GL11.glDrawElements(GL11.GL_TRIANGLES,6 , GL11.GL_UNSIGNED_INT, 0);
// Put everything back to default (deselect)
GL15.glBindBuffer(GL15.GL_ELEMENT_ARRAY_BUFFER, 0);
GL20.glDisableVertexAttribArray(0);
GL20.glDisableVertexAttribArray(1);
GL20.glDisableVertexAttribArray(2);
GL20.glUseProgram(0);
EDIT:
I check for an error on almost everything I left it out because it gave me no output. This is my method for checking for an error:
private void exitOnGLError(String errorMessage) { //Method to check if any opengl errors occured
int errorValue = GL11.glGetError();
if (errorValue != GL11.GL_NO_ERROR) {
String errorString = GLU.gluErrorString(errorValue);
System.err.println("ERROR - " + errorMessage + ": " + errorString);
if (Display.isCreated()) Display.destroy();
System.exit(-1);
}
}
Linking shaders:
loadShader("res/shaders/vert21.glsl",GL20.GL_VERTEX_SHADER);
loadShader("res/shaders/frag21.glsl",GL20.GL_FRAGMENT_SHADER);
shaderProgramID = GL20.glCreateProgram(); //Create a new shader program
for (Integer id : shaders) {
GL20.glAttachShader(shaderProgramID, id); //attach all the custom shaders to the program
}
// Position information will be attribute 0
GL20.glBindAttribLocation(shaderProgramID, 0, "in_Position");
// Color information will be attribute 1
GL20.glBindAttribLocation(shaderProgramID, 1, "in_Color");
// Textute information will be attribute 2
GL20.glBindAttribLocation(shaderProgramID, 2, "in_TextureCoord");
GL20.glLinkProgram(shaderProgramID); //Link the program to lwjgl
GL20.glValidateProgram(shaderProgramID); //Compile and make sure program was setup correctly
GL20.glUseProgram(shaderProgramID); //Use the program so we can pick the texture unit before continuing
setTextureUnit0(shaderProgramID); //pick the unit and set it in the shader to use
Loading and compiling:
StringBuilder shaderSource = new StringBuilder();
int shaderID = 0;
try { //Read shader
BufferedReader reader = new BufferedReader(new InputStreamReader(ClassLoader.getSystemResourceAsStream(filename)));
String line;
while ((line = reader.readLine()) != null) {
shaderSource.append(line).append("\n");
}
reader.close();
} catch (IOException e) {
System.err.println("Could not read file.");
Logger.getGlobal().log(Level.WARNING, e.getMessage(), e);
System.exit(-1);
} catch (NullPointerException e) {
try {
BufferedReader reader = new BufferedReader(new InputStreamReader( new FileInputStream(filename)));
String line;
while ((line = reader.readLine()) != null) {
shaderSource.append(line).append("\n");
}
reader.close();
} catch (IOException e1) {
e1.printStackTrace(); //To change body of catch statement use File | Settings | File Templates.
}
}
shaderID = GL20.glCreateShader(type); //Create shader
GL20.glShaderSource(shaderID, shaderSource); //Link source
GL20.glCompileShader(shaderID); //Compile
//Check if compiled correctly
if (GL20.glGetShaderi(shaderID, GL20.GL_COMPILE_STATUS) == GL11.GL_FALSE) {
System.err.println(shaderID+" | Shader wasn't able to be compiled correctly.");
System.out.println(GL20.glGetShaderInfoLog(shaderID,GL20.glGetShaderi(shaderID,GL20.GL_INFO_LOG_LENGTH)));
}
this.exitOnGLError("loadShader");
Related
I'm trying to write a set of shaders to do per-vertex lighting with multiple lights, and textures. I think I'm running into the shader compiler optimizing out 'v_texture', one of my attribute variables, because glVertexAttribLocation is failing to find it.
Here's my vertex shader code:
attribute vec3 v_position;
attribute vec3 v_normal;
attribute vec2 v_texture;
varying vec4 color;
varying vec2 texCoord;
const int MAX_LIGHTS = 8;
uniform struct lightSource
{
vec4 position;
vec4 color;
vec3 coneDirection;
float coneAngle;
float ambientFactor;
} sceneLights[MAX_LIGHTS];
uniform mat4 modelView;
uniform mat4 Projection;
uniform float shininess;
uniform int numLights;
vec4 applyLight(lightSource light)
{
vec4 outColor;
float attenuation;
vec3 surfacePos = (modelView * vec4(v_position.xyz, 1.0)).xyz;
vec3 toLight;
if(light.position.w == 0.0)
{
toLight = normalize(light.position.xyz);
attenuation = 1.0;
}
else
{
toLight = normalize(light.position.xyz - surfacePos);
float distanceToLight = length(light.position.xyz - surfacePos);
float lightAngle = degrees(acos(dot(-surfacePos, normalize(light.coneDirection))));
if(lightAngle > light.coneAngle)
{
attenuation = 0.0;
}
else
{
attenuation = 1.0/(1.0 + (0.1 * pow(distanceToLight, 2.0)));
}
}
vec3 Eye = normalize(-surfacePos);
vec3 Halfway = normalize(toLight + Eye);
vec3 worldNormal = normalize(modelView * vec4(v_normal, 0.0)).xyz;
vec4 ambient = vec4(light.ambientFactor * vec3(light.color.xyz), 1.0);
float Kd = max(dot(toLight, worldNormal), 0.0);
vec4 diffuse = Kd * light.color;
float Ks = pow(max(dot(worldNormal, Halfway), 0.0), shininess);
vec4 specular = Ks * light.color;
if(dot(toLight, worldNormal) < 0.0)
{
specular = vec4(0.0, 0.0, 0.0, 0.0);
}
outColor = ambient + (attenuation * (diffuse + specular));
outColor.a = 1.0;
return outColor;
}
void main(void)
{
vec4 colorSum;
colorSum = vec4(0, 0, 0, 0);
for(int i = 0; i < MAX_LIGHTS; i++)
{
if(i >= numLights)
{
break;
}
colorSum += applyLight(sceneLights[i]);
}
colorSum.xyzw = normalize(colorSum.xyzw);
vec3 gammaCorrection = vec3(1.0/2.2);
color = vec4(pow(vec3(colorSum.xyz), gammaCorrection), 1.0);
texCoord = v_texture;
gl_Position = Projection * modelView * vec4(v_position.xyz, 1.0);
}
And the fragment shader:
varying vec4 color;
varying vec2 texCoord;
uniform sampler2D texSampler;
void main(void)
{
gl_FragColor = (color * texture2D(texSampler, texCoord.xy));
}
I've been over the code top to bottom but I just can't see where my problem is. I'm assigning v_texture to the texCoord, and passing it to the frag shader, where I'm using it together with the final lighting result from the vertex shader to yield the final color. I'm checking for shader errors when I compile them, and I'm not getting anything. My only guess at the moment is that maybe gl_FragColor = (color * texture2D(texSampler, texCoord.xy)) isn't a valid statement, but then shouldn't this have caught it?
glGetShaderiv(fragment_shader, GL_COMPILE_STATUS, &shader_status);
if (!shader_status)
{
GLchar InfoLog[1024];
glGetShaderInfoLog(fragment_shader, sizeof(InfoLog), NULL, InfoLog);
fprintf(stderr, "Fragment Shader %d: '%s'\n", fragment_shader, InfoLog);
}
Edit: I probably should have put this in here in the first place, but this snippet is the shader section from my C++ program's initialize() function. The only one of the glGetAttribLocation calls to fail is for v_texture.
// Begin shader loading.
//compile the shaders
GLuint vertex_shader = glCreateShader(GL_VERTEX_SHADER);
GLuint fragment_shader = glCreateShader(GL_FRAGMENT_SHADER);
GLint shader_status;
pass=new char [2048];
unsigned int len;
//Give a maximum number of attempts to load the vertex shader
int attempts=10;
//Load the vertex shader
do
{
loader.load("lighting.vsh");
shaderCode = loader.hold.c_str();
len=loader.length;
pass=shaderCode;
attempts-=1;
}
while(len!=pass.length()&& attempts>0);
//Pass the temperary variable to a pointer
tmp = pass.c_str();
// Vertex shader first
glShaderSource(vertex_shader, 1,&tmp, NULL);
glCompileShader(vertex_shader);
//check the compile status
glGetShaderiv(vertex_shader, GL_COMPILE_STATUS, &shader_status);
if (!shader_status)
{
GLchar InfoLog[1024];
glGetShaderInfoLog(vertex_shader, sizeof(InfoLog), NULL, InfoLog);
fprintf(stderr, "Vertex Shader %d: '%s'\n", vertex_shader, InfoLog);
}
const char *fs=loader.load("lighting.fsh");
// Now the Fragment shader
glShaderSource(fragment_shader, 1, &fs, NULL);
glCompileShader(fragment_shader);
//check the compile status
glGetShaderiv(fragment_shader, GL_COMPILE_STATUS, &shader_status);
if (!shader_status)
{
GLchar InfoLog[1024];
glGetShaderInfoLog(fragment_shader, sizeof(InfoLog), NULL, InfoLog);
fprintf(stderr, "Fragment Shader %d: '%s'\n", fragment_shader, InfoLog);
}
//Now we link the 2 shader objects into a program
//This program is what is run on the GPU
program = glCreateProgram();
glAttachShader(program, vertex_shader);
glAttachShader(program, fragment_shader);
glLinkProgram(program);
//check if everything linked ok
glGetProgramiv(program, GL_LINK_STATUS, &shader_status);
if(!shader_status)
{
std::cerr << "[F] THE SHADER PROGRAM FAILED TO LINK" << std::endl;
return false;
}
//Now we set the locations of the attributes and uniforms
//this allows us to access them easily while rendering
loc_position = glGetAttribLocation(program,
const_cast<const char*>("v_position"));
if(loc_position == -1)
{
std::cerr << "Error: POSITION NOT FOUND IN SHADER" << std::endl;
return false;
}
loc_normals = glGetAttribLocation(program, const_cast<const char*>("v_normal"));
if(loc_normals == -1)
{
std::cerr << "Error: NORMALS NOT FOUND IN SHADER" << std:: endl;
return false;
}
loc_texture = glGetAttribLocation(program, const_cast<const char*>("v_texture"));
if(loc_texture == -1)
{
std::cerr << "[F] TEXTURE NOT FOUND IN SHADER" << std::endl;
return false;
}
// Begin light initialization.
Our application crashes on old Nvidia drivers..
Debug code is here
Looking around, here they say it is often due to an incorrect vertex attribute setup
This is how I setup my vbo and vao:
/**
* Init Vbo/vao.
*/
float[] vertexData = new float[]{
0, 0,
1, 0,
1, 1};
debugVbo = new int[1];
gl3.glGenBuffers(1, debugVbo, 0);
gl3.glBindBuffer(GL3.GL_ARRAY_BUFFER, debugVbo[0]);
{
FloatBuffer buffer = GLBuffers.newDirectFloatBuffer(vertexData);
gl3.glBufferData(GL3.GL_ARRAY_BUFFER, vertexData.length * Float.BYTES, buffer, GL3.GL_STATIC_DRAW);
}
gl3.glBindBuffer(GL3.GL_ARRAY_BUFFER, 0);
debugVao = new int[1];
gl3.glGenVertexArrays(1, debugVao, 0);
gl3.glBindVertexArray(debugVao[0]);
{
gl3.glBindBuffer(GL3.GL_ARRAY_BUFFER, debugVbo[0]);
{
gl3.glEnableVertexAttribArray(0);
{
gl3.glVertexAttribPointer(0, 2, GL3.GL_FLOAT, false, 0, 0);
}
}
gl3.glBindBuffer(GL3.GL_ARRAY_BUFFER, 0);
}
gl3.glBindVertexArray(0);
}
And this is how I render:
public static void render(GL3 gl3) {
gl3.glClear(GL3.GL_DEPTH_BUFFER_BIT | GL3.GL_COLOR_BUFFER_BIT);
gl3.glUseProgram(textureProgram);
{
gl3.glBindVertexArray(debugVao[0]);
{
gl3.glActiveTexture(GL3.GL_TEXTURE0);
gl3.glBindTexture(GL3.GL_TEXTURE_2D, texture[0]);
gl3.glBindSampler(0, EC_Samplers.pool[EC_Samplers.Id.clampToEdge_nearest_0maxAn.ordinal()]);
{
gl3.glDrawArrays(GL3.GL_TRIANGLES, 0, 3);
}
gl3.glBindTexture(GL3.GL_TEXTURE_2D, 0);
gl3.glBindSampler(0, 0);
}
gl3.glBindVertexArray(0);
}
gl3.glUseProgram(0);
}
This is my VS:
#version 330
layout (location = 0) in vec2 position;
uniform mat4 modelToCameraMatrix;
uniform mat4 cameraToClipMatrix;
out vec2 fragmentUV;
void main()
{
gl_Position = cameraToClipMatrix * modelToCameraMatrix * vec4(position, 0, 1);
fragmentUV = position;
}
And my FS:
#version 330
in vec2 fragmentUV;
out vec4 outputColor;
uniform sampler2D textureNode;
void main()
{
outputColor = texture(textureNode, fragmentUV);
}
I read and re-read the same code since 2 days now, I can't find anything wrong.
I tried also defining a stride of 2*4=8, but same outcome..
I can't believe it.
Problem lied somewhere else, where I was initializing my samplers
public static void init(GL3 gl3) {
pool = new int[Id.size.ordinal()];
gl3.glGenSamplers(Id.size.ordinal(), pool, 0);
gl3.glSamplerParameteri(pool[Id.clampToEdge_nearest_0maxAn.ordinal()],
GL3.GL_TEXTURE_WRAP_S, GL3.GL_CLAMP_TO_EDGE);
gl3.glSamplerParameteri(pool[Id.clampToEdge_nearest_0maxAn.ordinal()],
GL3.GL_TEXTURE_WRAP_T, GL3.GL_CLAMP_TO_EDGE);
gl3.glSamplerParameteri(pool[Id.clampToEdge_nearest_0maxAn.ordinal()],
GL3.GL_TEXTURE_MIN_FILTER, GL3.GL_NEAREST);
gl3.glSamplerParameteri(pool[Id.clampToEdge_nearest_0maxAn.ordinal()],
GL3.GL_TEXTURE_MAG_FILTER, GL3.GL_NEAREST);
gl3.glSamplerParameteri(pool[Id.clampToEdge_nearest_0maxAn.ordinal()],
GL3.GL_TEXTURE_MAX_ANISOTROPY_EXT, 0);
}
The crash was caused by setting the max anisotropy to 0... 1 resolved the crash..
Ps: also glSamplerParameterf instead glSamplerParameteri since it is a float value..
Anyway it is weird because that code was since since a lot of time and never trigger the violation previously.. I don't know.. maybe some latter code modification made in a way that the Nvidia driver couldn't detect anymore the problem and fix it by itself, who knows..
I am attempting to use four shaders: A vertex Shader (VS), a Tessellation Control Shader (TCS), a Tessellation Evaluation Shader (TES), and a Fragment Shader (FS).
However, when I attempt to load these shaders, I get:
This has been most baffling, and I have already spent a couple of hours trying to sort it out. However, I cannot see "gl_Vertex" anywhere in my code, so I am stuck really. I don't even know which shader is the problem.
Here is my current code for loading shaders (It looks like a lot, but it's really all just repeated code with slight changes):
public static int loadShaderPair(String vertexShaderLocation, String fragmentShaderLocation, String tesShaderLocation, String tesscontrolShaderLocation) {
int shaderProgram = glCreateProgram();
int vertexShader = glCreateShader(GL_VERTEX_SHADER);
int fragmentShader = glCreateShader(GL_FRAGMENT_SHADER);
int tesscontrolShader = glCreateShader(GL40.GL_TESS_CONTROL_SHADER);
int tesShader = glCreateShader(GL40.GL_TESS_EVALUATION_SHADER);
StringBuilder vertexShaderSource = new StringBuilder();
StringBuilder fragmentShaderSource = new StringBuilder();
StringBuilder tesShaderSource = new StringBuilder();
StringBuilder tesscontrolShaderSource = new StringBuilder();
BufferedReader tesShaderFileReader = null;
try {
tesShaderFileReader = new BufferedReader(new FileReader(tesShaderLocation));
String line;
while ((line = tesShaderFileReader.readLine()) != null) {
tesShaderSource.append(line).append('\n');
}
} catch (IOException e) {
e.printStackTrace();
return -1;
} finally {
if (tesShaderFileReader != null) {
try {
tesShaderFileReader.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
BufferedReader tesscontrolShaderFileReader = null;
try {
tesscontrolShaderFileReader = new BufferedReader(new FileReader(tesscontrolShaderLocation));
String line;
while ((line = tesscontrolShaderFileReader.readLine()) != null) {
tesscontrolShaderSource.append(line).append('\n');
}
} catch (IOException e) {
e.printStackTrace();
return -1;
} finally {
if (tesscontrolShaderFileReader != null) {
try {
tesscontrolShaderFileReader.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
BufferedReader vertexShaderFileReader = null;
try {
vertexShaderFileReader = new BufferedReader(new FileReader(vertexShaderLocation));
String line;
while ((line = vertexShaderFileReader.readLine()) != null) {
vertexShaderSource.append(line).append('\n');
}
} catch (IOException e) {
e.printStackTrace();
return -1;
} finally {
if (vertexShaderFileReader != null) {
try {
vertexShaderFileReader.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
BufferedReader fragmentShaderFileReader = null;
try {
fragmentShaderFileReader = new BufferedReader(new FileReader(fragmentShaderLocation));
String line;
while ((line = fragmentShaderFileReader.readLine()) != null) {
fragmentShaderSource.append(line).append('\n');
}
} catch (IOException e) {
e.printStackTrace();
return -1;
} finally {
if (fragmentShaderFileReader != null) {
try {
fragmentShaderFileReader.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
glShaderSource(vertexShader, vertexShaderSource);
glCompileShader(vertexShader);
if (glGetShaderi(vertexShader, GL_COMPILE_STATUS) == GL_FALSE) {
System.err.println("Vertex shader wasn't able to be compiled correctly. Error log:");
System.err.println(glGetShaderInfoLog(vertexShader, 1024));
return -1;
}
glShaderSource(tesscontrolShader, tesscontrolShaderSource);
glCompileShader(tesscontrolShader);
if (glGetShaderi(tesscontrolShader, GL_COMPILE_STATUS) == GL_FALSE) {
System.err.println("tesscontrol shader wasn't able to be compiled correctly. Error log:");
System.err.println(GL11.glGetString(GL11.glGetError()));
System.err.println(glGetShaderInfoLog(tesscontrolShader, 1024));
}
glShaderSource(fragmentShader, fragmentShaderSource);
glCompileShader(fragmentShader);
if (glGetShaderi(fragmentShader, GL_COMPILE_STATUS) == GL_FALSE) {
System.err.println("Fragment shader wasn't able to be compiled correctly. Error log:");
System.err.println(GL11.glGetString(GL11.glGetError()));
System.err.println(glGetShaderInfoLog(fragmentShader, 1024));
}
glShaderSource(tesShader, tesShaderSource);
glCompileShader(tesShader);
if (glGetShaderi(vertexShader, GL_COMPILE_STATUS) == GL_FALSE) {
System.err.println("Tessellation shader wasn't able to be compiled correctly. Error log:");
System.err.println(glGetShaderInfoLog(tesShader, 1024));
return -1;
}
glAttachShader(shaderProgram, vertexShader);
glAttachShader(shaderProgram, tesShader);
glAttachShader(shaderProgram, tesscontrolShader);
glAttachShader(shaderProgram, fragmentShader);
glLinkProgram(shaderProgram);
if (glGetProgrami(shaderProgram, GL_LINK_STATUS) == GL_FALSE) {
System.err.println("Shader program wasn't linked correctly.");
System.err.println(GL11.glGetString(GL11.glGetError()));
System.err.println(glGetProgramInfoLog(shaderProgram, 1024));
System.exit(1);
return -1;
}
glDeleteShader(vertexShader);
glDeleteShader(fragmentShader);
glDeleteShader(tesShader);
glDeleteShader(tesscontrolShader);
return shaderProgram;
}
And here are my shaders:
VS:
layout (location = 0) in vec3 Position_VS_in;
layout (location = 1) in vec2 TexCoord_VS_in;
layout (location = 2) in vec3 Normal_VS_in;
uniform mat4 gWorld;
out vec3 WorldPos_CS_in;
out vec2 TexCoord_CS_in;
out vec3 Normal_CS_in;
void main()
{
WorldPos_CS_in = (gWorld * vec4(Position_VS_in, 1.0)).xyz;
TexCoord_CS_in = TexCoord_VS_in;
Normal_CS_in = (gWorld * vec4(Normal_VS_in, 0.0)).xyz;
gl_Position = ftransform();
}
TCS:
// define the number of CPs in the output patch
layout (vertices = 3) out;
uniform vec3 gEyeWorldPos;
// attributes of the input CPs
in vec3 WorldPos_CS_in[];
in vec2 TexCoord_CS_in[];
in vec3 Normal_CS_in[];
// attributes of the output CPs
out vec3 WorldPos_ES_in[];
out vec2 TexCoord_ES_in[];
out vec3 Normal_ES_in[];
float GetTessLevel(float Distance0, float Distance1)
{
float AvgDistance = (Distance0 + Distance1) / 2.0;
if (AvgDistance <= 2.0) {
return 10.0;
}
else if (AvgDistance <= 5.0) {
return 7.0;
}
else {
return 3.0;
}
}
void main()
{
// Set the control points of the output patch
TexCoord_ES_in[gl_InvocationID] = TexCoord_CS_in[gl_InvocationID];
Normal_ES_in[gl_InvocationID] = Normal_CS_in[gl_InvocationID];
WorldPos_ES_in[gl_InvocationID] = WorldPos_CS_in[gl_InvocationID];
// Calculate the distance from the camera to the three control points
float EyeToVertexDistance0 = distance(gEyeWorldPos, WorldPos_ES_in[0]);
float EyeToVertexDistance1 = distance(gEyeWorldPos, WorldPos_ES_in[1]);
float EyeToVertexDistance2 = distance(gEyeWorldPos, WorldPos_ES_in[2]);
// Calculate the tessellation levels
gl_TessLevelOuter[0] = GetTessLevel(EyeToVertexDistance1, EyeToVertexDistance2);
gl_TessLevelOuter[1] = GetTessLevel(EyeToVertexDistance2, EyeToVertexDistance0);
gl_TessLevelOuter[2] = GetTessLevel(EyeToVertexDistance0, EyeToVertexDistance1);
gl_TessLevelInner[0] = gl_TessLevelOuter[2];
}
TES:
layout(triangles, equal_spacing, ccw) in;
uniform mat4 gVP;
uniform sampler2D gDisplacementMap;
uniform float gDispFactor;
in vec3 WorldPos_ES_in[];
in vec2 TexCoord_ES_in[];
in vec3 Normal_ES_in[];
out vec3 WorldPos_FS_in;
out vec2 TexCoord_FS_in;
out vec3 Normal_FS_in;
vec2 interpolate2D(vec2 v0, vec2 v1, vec2 v2)
{
return vec2(gl_TessCoord.x) * v0 + vec2(gl_TessCoord.y) * v1 + vec2(gl_TessCoord.z) * v2;
}
vec3 interpolate3D(vec3 v0, vec3 v1, vec3 v2)
{
return vec3(gl_TessCoord.x) * v0 + vec3(gl_TessCoord.y) * v1 + vec3(gl_TessCoord.z) * v2;
}
void main()
{
// Interpolate the attributes of the output vertex using the barycentric coordinates
TexCoord_FS_in = interpolate2D(TexCoord_ES_in[0], TexCoord_ES_in[1], TexCoord_ES_in[2]);
Normal_FS_in = interpolate3D(Normal_ES_in[0], Normal_ES_in[1], Normal_ES_in[2]);
Normal_FS_in = normalize(Normal_FS_in);
WorldPos_FS_in = interpolate3D(WorldPos_ES_in[0], WorldPos_ES_in[1], WorldPos_ES_in[2]);
// Displace the vertex along the normal
float Displacement = texture(gDisplacementMap, TexCoord_FS_in.xy).x;
WorldPos_FS_in += Normal_FS_in * Displacement * gDispFactor;
gl_Position = gVP * vec4(WorldPos_FS_in, 1.0);
}
FS:
varying vec4 position_in_view_space;
uniform sampler2D color_texture;
void main()
{
float dist = distance(position_in_view_space,
vec4(0.0, 0.0, 0.0, 1.0));
if (dist < 1000.0)
{
gl_FragColor = gl_Color;
// color near origin
}
else
{
gl_FragColor = gl_Color;
//kill;
//discard;
//gl_FragColor = vec4(0.3, 0.3, 0.3, 1.0);
// color far from origin
}
}
If for any reason it helps, my PC supports up to (and including) OpenGL 4.0.
Since I have been unable to work out how I am supposedly using a line of code I am not using, I am hoping one of you will be able to diagnose the issue.
Well, the error message is very clear, and the reason is this:
layout (location = 0) in vec3 Position_VS_in;
[...]
gl_Position = ftransform();
ftransform is a legacy function which uses the legacy bultin vertex position attribute gl_Vertex to transform a vertex according to the also legacy bultin matrix uniforms.
The GL spec also requires the generic vertex attribute 0 to alias the old builtin gl_Vertex, so your attribute index 0 is blocked by this and you must not assign some other attribute to this.
Now it is totally unclear why you use ftransform here. It seems like you don't want that at all. But I can't be sure about that. But it will definitively not work that way. You shouldn't use that deprecated stuff at all, in my opinion.
UPDATE 1
Note that ftransform is in princicple equivalent to gl_ModelViewProjectionMatrix * gl_Vertex, with gl_ModelViewProjectionMatrix being a builtin uniform representing the product P * MV of the matrices you set for GL_PROJECTION and GL_MODELVIEW using the also-deprecated GL matrix stack, and gl_Vertex being the builtin vertex position attribute set with glVertex.../glVertexPointer/glVertexAttribPointer(0,...). Both can be replaced by user-defined attributes/uniforms.
The only twist with ftransform is that it is also guaranteed to get the exact same result as rendering with the fixed function pipeline does, for the same inputs. That was useful for multi-pass algorithms where some passed needed to render with shaders, while others used the fixed function pipelinew. Such a function was needed because there might be slight numerical differences if the shader does not use the exact same formula as the GL implementation when rendering without shaders.
I'm checking the logs, and everything compiles fine. The shader looks like this:
Vertex:
#version 330 core
layout(location = 0) in struct InData {
vec3 position;
vec4 color;
} inData;
out struct OutData {
vec3 position;
vec4 color;
} outData;
void main()
{
outData.position = inData.position;
outData.color = inData.color;
}
Fragment:
#version 330 core
in struct InData {
vec2 position;
vec4 color;
} inData;
out vec4 color;
void main(){
color = inData.color;
}
I'm preparing the shader like this:
public Shader(string src, ShaderType type)
{
shaderId = GL.CreateShader(type);
GL.ShaderSource(shaderId, GetShader(src));
GL.CompileShader(shaderId);
EventSystem.Log.Message(GL.GetShaderInfoLog(shaderId));
EventSystem.Log.Message("GLERROR: " + GL.GetError());
packs = new List<ShaderPack>();
}
public void Attach(ShaderPack pack)
{
packs.Add(pack);
GL.AttachShader(pack.ProgramID, shaderId);
EventSystem.Log.Message(GL.GetProgramInfoLog(pack.ProgramID));
EventSystem.Log.Message("GLERROR: " + GL.GetError());
}
Then I compile the shader:
public void Compile()
{
if(program >= 0)
GL.DeleteProgram(program);
program = GL.CreateProgram();
foreach (var s in shaders.Values)
s.Attach(this);
EventSystem.Log.Message(GL.GetProgramInfoLog(program));
EventSystem.Log.Message("GLERROR: " + GL.GetError());
}
And then I'm trying to use it:
mesh = new Mesh();
mesh.AddTriangle(
new Vector3(0, 0, 0), new Vector4(1, 0, 0, 1),
new Vector3(0, sizeY, 0), new Vector4(0, 1, 0, 1),
new Vector3(sizeX, sizeY, 0), new Vector4(0, 0, 1, 1));
mesh.RefreshBuffer();
shaderPack.Apply();
shaderPack.SetVertexAttribute<Mesh.MeshData1>("vertex", 0, mesh.meshData);
EventSystem.Log.Message("GLERROR: " + GL.GetError());
In Apply GL.UseProgram is called and GetError returns "Invalid Operation"
UPDATE:
Okay I changed the code:
public void Compile()
{
if(program >= 0)
GL.DeleteProgram(program);
program = GL.CreateProgram();
foreach (var s in shaders.Values)
s.Attach(this);
// GL.LinkProgram(program);
//GL.ValidateProgram(program);
GL.ValidateProgram(program);
EventSystem.Log.Message("Validate: " + GL.GetProgramInfoLog(program) + " - " + GL.GetError());
}
public void Apply()
{
GL.UseProgram(program);
EventSystem.Log.Message("GLERROR (Apply): " + GL.GetError());
}
And the output is
[23:25:55][Log]: Validate: - NoError
[23:25:55][Log]: GLERROR (Apply): InvalidOperation
edit: Okay I changed the vertex shaders:
#version 330 core
layout(location = 0) in struct InData {
vec3 position;
vec4 color;
} inData;
void main()
{
gl_Position = vec4(inData.position, 1);
}
...
#version 330 core
//in struct InData {
// vec2 position;
// vec4 color;
//} inData;
out vec4 color;
void main(){
color = vec4(1,0,0,1);
}
It compiles without errors, but I have a blank screen...
Pre-Rollback:
EDIT: Okay, I suspect the problem lies here:
public void VertexAttribute<T>(int loc, ShaderPack p, T[] dataArray) where T : struct
{
int buf;
GL.GenBuffers(1, out buf);
GL.BindBuffer(BufferTarget.ArrayBuffer, buf);
GL.BufferData<T>(BufferTarget.ArrayBuffer, (IntPtr)(dataArray.Length * Marshal.SizeOf(typeof(T))), dataArray, BufferUsageHint.StaticDraw);
GL.EnableVertexAttribArray(0);
GL.VertexAttribPointer<T>(loc, 2, VertexAttribPointerType.Float, false, 0, ref dataArray[0]);
GL.BindBuffer(BufferTarget.ArrayBuffer, 0);
}
I'm passing this with an Array of the following type:
public struct MeshData1
{
public Vector3 vertex;
public Vector4 color;
public MeshData1(Vector3 vertex, Vector4 color)
{
this.vertex = vertex;
this.color = color;
}
}
And the input looks like this:
#version 330 core
layout(location = 0) in struct InData {
vec3 position;
vec4 color;
} inData;
void main()
{
gl_Position = vec4(inData.position, 1.0);
}
What am I doing wrong?
Two problems immediately come to mind:
You never linked the attached shader stages in your program object (most important)
The string output by glGetProgramInfoLog (...) is only generated/updated after linking or validating a GLSL program.
To fix this, you should make a call to glLinkProgram (...) after attaching your shaders, and also understand that up until you do this the program info log will be undefined.
glValidateProgram (...) is another way of updating the contents of the program info log. In addition to generating the info log, this function will also return whether your program is in a state suitable for execution or not. The result of this operation is stored in a per-program state called GL_VALIDATE_STATUS.
I'm making a crossplatform OpenGL program. However, I've encountered a problem, where glGetUniformLocation, which should return the location of a uniform variable in my shader program, returns -1, and it only occurs on Linux (Raspbian distro, ran on Raspberry PI), and on Windows the same code works perfectly! Here's my code:
Load Shader program function:
int shader, status;
programID = glCreateProgram();
// Load vertex shader
shader = LoadShaderFromString(GL_VERTEX_SHADER, Tools::GetFileAsString("VertexShader.glsl"), "Unable to compile vertex shader.\n");
glAttachShader(programID, shader);
// Load pixel shader
shader = LoadShaderFromString(GL_FRAGMENT_SHADER, Tools::GetFileAsString("FilterPixelShader.glsl"), "Unable to compile pixel shader.\n");
glAttachShader(programID, shader);
// Link the program
glLinkProgram(programID);
glGetProgramiv(programID, GL_LINK_STATUS, &status);
if (status == 0)
{
Log("Unable to link filter shader program.\n");
PrintProgramLog(programID);
Fail(); // Quits program
}
// returns -1 here!
frameTextureLocation = glGetUniformLocation(programID, "FrameTextureUnit");
if (frameTextureLocation == -1)
{
int errorCode = glGetError();
Log(string("Error retrieving variable frameTextureLocation from shader program: "));
Log((const char*)glewGetErrorString(errorCode))
Log("!\n");
Fail();
}
LoadShaderFromString:
int Shader::LoadShaderFromString(int type, const string& shaderSource, const string& errorMessage)
{
int shader, status;
const char* programSource;
shader = glCreateShader(type);
programSource = shaderSource.c_str();
glShaderSource(shader, 1, &programSource, nullptr);
glCompileShader(shader);
glGetShaderiv(shader, GL_COMPILE_STATUS, &status);
if (status == 0)
{
Log(errorMessage);
PrintShaderLog(shader);
Fail();
}
return shader;
}
Lastly, the shader itself:
uniform sampler2D FrameTextureUnit;
uniform sampler2D BackgroundTextureUnit;
#if __VERSION__ >= 130
// Texture coordinate
in vec2 texCoord;
// Final color
out vec4 gl_FragColor;
#else
// Texture coordinate
varying vec2 texCoord;
#endif
uniform float Tolerance; // Tolerance for color difference
uniform vec4 FilterColor; // Color of the filter
void main()
{
vec4 pixel = texture2D(FrameTextureUnit, texCoord);
vec4 background = texture2D(BackgroundTextureUnit, texCoord);
float difference = abs(background.x - pixel.x)
+ abs(background.y - pixel.y)
+ abs(background.z - pixel.z);
if (difference > Tolerance)
{
gl_FragColor = FilterColor;
}
else
{
// Y = 0.2126 R + 0.7152 G + 0.0722 B
float gray = pixel.x * 0.2126 + pixel.y * 0.7152 + pixel.z * 0.0722;
gl_FragColor = vec4(gray, gray, gray, 1);
}
}
Does anyone know why this might be happening? :( It's worth adding that the error handling code:
int errorCode = glGetError();
Log(string("Error retrieving variable frameTextureLocation from shader program: "));
Log((const char*)glewGetErrorString(errorCode));
Prints "Error retrieving variable frameTextureLocation from shader program: No error".
Always specify GLSL version at the top of your shaders, otherwise it defaults to a very old version. It must be the first line. It will also eliminate the need for version checking inline.
#version 150
// rest of shader here