I have a problem with displaying textures with GLSL in OpenGL 3.3 (Core profile). I have triple-checked everything and still can't find mistake. I'm using SDL for window handling and for texture loading.
This is my texture loading function
glEnable (GL_TEXTURE_2D);
glGenTextures(1, &generated_texture);
glBindTexture(GL_TEXTURE_2D, generated_texture);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_WRAP_S,GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_WRAP_T,GL_CLAMP_TO_EDGE);
glTexImage2D(GL_TEXTURE_2D, 0, GL_BGRA, image->w, image->h, 0, GL_BGRA, GL_UNSIGNED_BYTE, image->pixels);
Passing to shaders
glActiveTexture(GL_TEXTURE0);
glUniform1i( glGetUniformLocation(shader, "texture_diffuse"), 0 );
glBindTexture(GL_TEXTURE_2D, texture_diffuse);
Vertex Shader
#version 330 core
struct Light
{
vec4 ambient;
vec4 diffuse;
vec4 specular;
vec4 position;
};
struct Material
{
vec4 ambient;
vec4 diffuse;
vec4 specular;
vec3 emission;
float shininess;
float reflectivity;
float ior;
float opacity;
};
layout(location = 0) in vec4 VertexPosition;
layout(location = 1) in vec3 VertexNormal;
layout(location = 2) in vec2 VertexTexture;
uniform mat4 PMatrix; //Camera projection matrix
uniform mat4 VMatrix; //Camera view matrix
uniform mat3 NMatrix; //MVMatrix ... -> converted into normal matrix (inverse transpose operation)
uniform mat4 MVPMatrix;
uniform Light light;
uniform Material material;
uniform sampler2D texture_diffuse;
//The prefix ec means Eye Coordinates in the Eye Coordinate System
out vec4 ecPosition;
out vec3 ecLightDir;
out vec3 ecNormal;
out vec3 ecViewDir;
out vec2 texture_coordinate;
void main()
{
ecPosition = VMatrix * VertexPosition;
ecLightDir = vec3(VMatrix * light.position - ecPosition);
ecNormal = NMatrix * VertexNormal;
ecViewDir = -vec3(ecPosition);
texture_coordinate = VertexTexture;
gl_Position = PMatrix * ecPosition;
}
Fragment Shader
#version 330 core
in vec3 ecNormal;
in vec4 ecPosition;
in vec3 ecLightDir;
in vec3 ecViewDir;
in vec2 texture_coordinate;
out vec4 FragColor;
struct Light
{
vec4 ambient;
vec4 diffuse;
vec4 specular;
vec4 position;
};
struct Material
{
vec4 ambient;
vec4 diffuse;
vec4 specular;
vec3 emission;
float shininess;
float reflectivity;
float ior;
float opacity;
};
uniform Light light;
uniform Material material;
uniform sampler2D texture_diffuse;
void main()
{
vec3 N = normalize(ecNormal);
vec3 L = normalize(ecLightDir);
vec3 V = normalize(ecViewDir);
float lambert = dot(N,L);
vec4 _tex = texture2D( texture_diffuse, texture_coordinate );
FragColor = _tex;
}
Also everything except textures works ( texture_coordinate etc. )
Does anyone see any possible error?
There are a few things I can see:
glEnable (GL_TEXTURE_2D);
This will just generate an error, as this enable is not valid in GL core profiles.
vec4 _tex = texture2D( texture_diffuse, texture_coordinate );
This will not compile, as the function texture2D is not available in GLSL3.30. It is called just texture and will derive the texture type from the sampler variable you call it with.
You should check for GL errors and especially the compile and link states of you shaders (and the info logs).
Related
I am trying to build lighting using this tutorial. However, lighting appears on wrong side of human object and I do not know why.
Normals were created per triangle. Vertices of a triangle basically have the same normal:
glm::vec3 calculateNormal(glm::vec3 vertice_1, glm::vec3 vertice_2, glm::vec3 vertice_3)
{
glm::vec3 vector_1 = vertice_2 - vertice_1;
glm::vec3 vector_2 = vertice_3 - vertice_1;
return glm::normalize(glm::cross(vector_1, vector_2));
}
Here is code for vertex shader:
#version 330 core
layout (location = 0) in vec3 pos;
layout (location = 1) in vec3 normal;
out vec4 vert_color;
out vec3 Normal;
out vec3 FragPos;
uniform mat4 model;
uniform mat4 view;
uniform mat4 projection;
uniform mat4 transform;
uniform vec4 color;
void main()
{
vert_color = color;
gl_Position = projection * view * model * transform * vec4(pos.x, pos.y, pos.z, 1.0);
FragPos = vec3(model * transform * vec4(pos, 1.0));
Normal = normal;
}
Fragment shader:
#version 330 core
uniform vec3 cameraPos;
uniform vec3 lightPos;
uniform vec3 lightColor;
in vec4 vert_color;
in vec3 FragPos;
in vec3 Normal;
out vec4 frag_color;
void main()
{
float ambientStrength = 0.1;
float specularStrength = 0.5;
vec3 ambient = ambientStrength * lightColor;
vec3 lightDir = normalize(lightPos - FragPos);
float diff = max(dot(Normal, lightDir), 0.0);
vec3 diffuse = diff * lightColor;
vec3 viewDir = normalize(cameraPos - FragPos);
vec3 reflectDir = reflect(-lightDir, Normal);
float spec = pow(max(dot(viewDir, reflectDir), 0.0), 32);
vec3 specular = specularStrength * spec * lightColor;
vec3 result = (ambient + diffuse + specular) * vec3(vert_color.x, vert_color.y, vert_color.z);
frag_color = vec4(result, vert_color.w);
}
Main loop:
wxGLCanvas::SetCurrent(*glContext);
glClearDepth(1.0f);
glEnable(GL_BLEND);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
glDepthFunc(GL_LEQUAL);
glEnable(GL_DEPTH_TEST);
glm::mat4 model, view, projection;
model = glm::translate(model, modelPos); // modelPos is
view = fpsCamera->getViewMatrix();
projection = fpsCamera->getProjectionMatrix(windowWidth, windowHeight);
color = glm::vec4(0.310f, 0.747f, 0.185f, 1.0f);
glm::vec3 lightPos = glm::vec3(0.0f, 1.0f, 0.0f);
glm::vec3 lightColor = glm::vec3(1.0f, 1.0f, 1.0f);
glm::mat4 phantomtTransformation;
phantomtTransformation = glm::rotate(phantomtTransformation, - glm::pi<float>() / 2.0f, glm::vec3(1.0f, 0.0f, 0.0f));
phantomtTransformation = glm::rotate(phantomtTransformation, - glm::pi<float>() , glm::vec3(0.0f, 0.0f, 1.0f));
ShaderProgram shaderProgram;
shaderProgram.loadShaders("Shaders/phantom.vert", "Shaders/phantom.frag");
glClearStencil(0);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
shaderProgram.use();
shaderProgram.setUniform("transform", phantomtTransformation);
shaderProgram.setUniform("model", model);
shaderProgram.setUniform("view", view);
shaderProgram.setUniform("projection", projection);
shaderProgram.setUniform("color", color);
shaderProgram.setUniform("lightColor", lightColor);
shaderProgram.setUniform("lightPos", lightPos);
shaderProgram.setUniform("cameraPos", fpsCamera->getPosition());
glStencilMask(0xFF); // Write to stencil buffer
glStencilOp(GL_KEEP, GL_KEEP, GL_REPLACE);
glStencilFunc(GL_ALWAYS, 0, 0xFF); // Set any stencil to 0
glStencilFunc(GL_ALWAYS, 1, 0xFF); // Set any stencil to object ID
m_pantomMesh->draw();
glStencilFunc(GL_ALWAYS, 0, 0xFF); // Set any stencil to 0 // no need for testing
glFlush();
wxGLCanvas::SwapBuffers();
View from front of the object:
View from back of the object:
EDIT:
In order to debug I removed object rotation matrix from main loop:
glm::mat4 phantomtTransformation;
phantomtTransformation = glm::rotate(phantomtTransformation, - glm::pi<float>() / 2.0f, glm::vec3(1.0f, 0.0f, 0.0f));
phantomtTransformation = glm::rotate(phantomtTransformation, - glm::pi<float>() , glm::vec3(0.0f, 0.0f, 1.0f));
shaderProgram.setUniform("transform", phantomtTransformation);
and changed line in fragment shader from
frag_color = vec4(result, vert_color.w);
to
frag_color = vec4(Normal, vert_color.w);
in order to visualize Normal values. As a result I noticed that when camera changes position phantom also changes color which means that normal values are also changing.
I think the cause of your problem is that you are not applying your model transformation to your normal vectors. Since you definitely do not want to skew them, you will have to create a special matrix for your normals.
As is explained further down the tutorial that you mentioned, the matrix can be constructed like this
Normal = mat3(transpose(inverse(model))) * aNormal;
in your vertex shader.
However, I highly recommend that you calculate the matrix in your application code instead, since you would calculate it per vertex in the above example.
Since you are using the glm library, it would look like this instead:
glm::mat3 model_normal = glm::mat3(glm::transpose(glm::inverse(model)));
You can then load your new model_normal matrix into the shader as a uniform mat3.
I am implementing a specular highlight in OpenGL as part of the phong model. Currently, the highlight moves when my camera moves rather that getting brighter or dimmer which obviously isn't the expected result. I have followed the tutorial on learnopengl.com
#version 330 core
in vec3 outColor;
in vec3 outNormal;
in vec3 fragPos;
out vec4 FragColor;
uniform vec3 lightPos = vec3(-2.0f, 0.0f, 0.0f);
uniform vec3 lightColor = vec3(1.0, 0.5f, 1.0f);
uniform vec3 viewPos;
float ambientStrength = 0.2;
float specularStrength = 0.5;
uniform sampler2D tex;
void main()
{
vec3 normal = normalize(outNormal);
vec3 lightDir = normalize(lightPos - fragPos);
//ambient lighitng
vec3 ambient = ambientStrength * lightColor;
//diffuse lighting
float diffuseFactor = max(dot(normal, lightDir), 0.0);
vec3 diffuse = diffuseFactor * lightColor;
//specular lighting
vec3 viewDir = normalize(viewPos - fragPos);
vec3 reflectDir = reflect(-lightDir, normal);
float spec = pow(max(dot(viewDir, reflectDir), 0.0), 128);
vec3 specular = specularStrength * spec * lightColor;
vec3 result = (ambient + diffuse + specular) * outColor;
FragColor = vec4(result, 1.0f);// texture(tex, outTexCoords);// vec4(0.0f, 1.0f, 0.0f, 1.0f);
}
I use vector as light position say (0.0f, 0.0f, 5.0f) and an object positioned at (0.0f, 0.0f, -10.0f) and a plane.
lightSpaceProjection = glm::ortho(-10.0f, 10.0f, -10.0f, 10.0f, 1.0f, 300.0f);
lightSpaceView= glm::lookAt(lightPosition, glm::vec3(0.0f), glm::vec3(0.0f, 1.0f, 0.0f));
lightSpaceMatrix = lightSpaceProjection * lightSpaceView;
I get a shadow moving with the camera everywhere, I want to know how to update the shadow map to render the right space shadow where the camera looks at.
I calculate the light space matrix as shown to send it to the vertex shader to render the shadow map from the light view, then send it again to the normal vertex shader to calculate which fragment is in shadow,
the light definition
DirectLight sun;
sun.direction = glm::vec3(0.0f, 10.0f, 5.0f);
sun.lightSpaceProjection = glm::ortho(-10.0f, 10.0f, -10.0f, 10.0f, 1.0f, 300.0f);
sun.lightSpaceView= glm::lookAt(sun.direction, glm::vec3(0.0f), glm::vec3(0.0f, 1.0f, 0.0f));
scene.addLight("sun", sun);
this is the render code
DirectLight& sun = dynamic_cast<DirectLight&>(this->getLight("sun", LIGHTTYPE_DIRECT));
glm::mat4 lightSpaceMatrix = (sun.lightSpaceProjection * sun.lightSpaceView);
glViewport(0, 0, SHADOW_WIDTH, SHADOW_HEIGHT);
glBindFramebuffer(GL_FRAMEBUFFER, depthMapFBO);
glClear(GL_DEPTH_BUFFER_BIT);
//glCullFace(GL_FRONT);
typedef std::map<std::string, Model>::iterator model_it;
depthShader.use();
glUniformMatrix4fv(glGetUniformLocation(depthShader.getProgramID(), "lightSpaceMatrix"), 1, GL_FALSE, glm::value_ptr(lightSpaceMatrix));
for (model_it it = phongModels.begin(); it != phongModels.end(); it++) {
((Model&) it->second).drawDepth(depthShader);
}
//glCullFace(GL_BACK);
glBindFramebuffer(GL_FRAMEBUFFER, 0);
// draw normal
glViewport(0, 0, WIDTH, HEIGHT);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
typedef std::map<std::string, Model>::iterator model_it;
phongShader.use();
glUniformMatrix4fv(glGetUniformLocation(phongShader.getProgramID(), "lightSpaceMatrix"), 1, GL_FALSE, glm::value_ptr(lightSpaceMatrix));
this->drawPhongLights(phongShader);
this->setViewUniforms(phongShader);
for (model_it it = phongModels.begin(); it != phongModels.end(); it++) {
glActiveTexture(GL_TEXTURE2);
glUniform1i(glGetUniformLocation(phongShader.getProgramID(), "shadowMap"), 2);
glBindTexture(GL_TEXTURE_2D, depthMap);
((Model&) it->second).drawPhong(phongShader, this->defCamera);
}
the depth vertex shader is
#version 330 core
layout (location = 0) in vec3 position;
uniform mat4 lightSpaceMatrix;
uniform mat4 model;
void main(){
gl_Position = lightSpaceMatrix * model * vec4(position, 1.0f);
}
and the normal vertex shader is
#version 330 core
layout (location = 0) in vec3 position;
layout (location = 2) in vec2 texCoord;
layout (location = 1) in vec3 normal;
out vec2 TexCoords;
out vec3 Normal;
out vec3 FragPos;
out vec3 LightPos;
out vec4 FragPosLightSpace;
uniform mat4 model;
uniform mat4 view;
uniform mat4 projection;
uniform vec3 lightPos;
uniform mat4 lightSpaceMatrix;
void main()
{
gl_Position = projection * view * model * vec4(position, 1.0f);
TexCoords = vec2(texCoord.s,1.0-texCoord.t);
Normal=normal;
FragPos = vec3(view * model * vec4(position, 1.0f));
LightPos = vec3(view * vec4(lightPos, 1.0));
FragPosLightSpace = lightSpaceMatrix * vec4(FragPos, 1.0);
}
and in fragment shader i calculate the shadow by this function
float directShadowCalculation(vec4 fragPosLightSpace,float bias){
vec3 projCoords = fragPosLightSpace.xyz / fragPosLightSpace.w;
projCoords = projCoords * 0.5 + 0.5;
float closestDepth = vec3(texture(shadowMap, projCoords.xy)).r;
float currentDepth = projCoords.z;
float shadow = 0.0;
vec2 texelSize = 1.0 / textureSize(shadowMap, 0);
for(int x = -1; x <= 1; ++x){
for(int y = -1; y <= 1; ++y){
float pcfDepth = texture(shadowMap, projCoords.xy + vec2(x, y) * texelSize).r;
shadow += currentDepth - bias > pcfDepth ? 1.0 : 0.0;
}
}
shadow /= 9.0;
if(projCoords.z > 1.0)
shadow = 0.0;
return shadow;
}
then apply the color by this one
vec3 calcDirectLight(DirectLight light){
vec3 color = vec3(texture(mat_diffuse, TexCoords));
vec3 norm = normalize(Normal);
vec3 lightDir = normalize( light.direction - FragPos);
float diff = max(dot(norm, lightDir), 0.0);
vec3 diffuse = light.diffuse * diff ;
vec3 viewDir = normalize(viewPos - FragPos);
vec3 reflectDir = reflect(-lightDir, norm);
float spec =0.0;
if(blinn){
vec3 halfwayDir = normalize(lightDir + viewDir);
spec = pow(max(dot(norm, halfwayDir), 0.0), 16.0);
}
else{
vec3 reflectDir = reflect(-lightDir, norm);
spec = pow(max(dot(viewDir, reflectDir), 0.0), 8.0);
}
//float spec = pow(max(dot(viewDir, reflectDir), 0.0), shininess);
vec3 specular = spec * light.specular;
float bias = max(0.05 * (1.0 - dot(norm, lightDir)), 0.005);
float shadow = directShadowCalculation(FragPosLightSpace,bias);
vec3 result =light.intensity* (light.ambient+ ((1.0 - shadow) * (diffuse + specular)))*color;
return result;
}
i don't know how to update the light space frustum with camera view
Solution:
the bug was in the vertex shader, this is the correct one:
#version 330 core
layout (location = 0) in vec3 position;
layout (location = 2) in vec2 texCoord;
layout (location = 1) in vec3 normal;
out vec2 TexCoords;
out vec3 Normal;
out vec3 FragPos;
out vec4 FragPosLightSpace;
uniform mat4 model;
uniform mat4 view;
uniform mat4 projection;
uniform vec3 lightPos;
uniform mat4 lightSpaceMatrix;
void main()
{
gl_Position = projection * view * model * vec4(position, 1.0f);
TexCoords = vec2(texCoord.s,1.0-texCoord.t);
Normal=transpose(inverse(mat3(model))) * normal;;
FragPos = vec3( model * vec4(position, 1.0f));
FragPosLightSpace = lightSpaceMatrix * vec4(FragPos, 1.0);
}
I'm very new to OpenGL and I've been working with setting up sky boxes, and finally fixed it thanks to some help here but now the reflection shader I've tried to set up by editing some I've found (so a sphere will have a basic reflection effect based on the cube map of my sky box) will not show any color but grey as shown in the image.
http://i.imgur.com/Th56Phg.png
I'm having no luck figuring out, here is my shader code:
Vertex Shader
#version 330 core
attribute vec3 position;
attribute vec2 texCoord;
attribute vec3 normal;
out vec3 Normal;
out vec3 Position;
uniform mat4 model;
uniform mat4 view;
uniform mat4 projection;
uniform mat4 transform;
void main()
{
gl_Position = transform * vec4(position, 1.0);
Normal = mat3(transpose(inverse(model))) * normal;
Position = vec3(model * vec4(position, 1.0f));
}
Fragment Shader
#version 330 core
in vec3 Normal;
in vec3 Position;
out vec4 color;
uniform vec3 cameraPos;
uniform samplerCube skybox;
void main()
{
vec3 I = normalize(Position - cameraPos);
vec3 R = reflect(I, normalize(Normal));
color = texture(skybox, R);
}
And finally this is my usage:
glm::mat4 model;
glm::mat4 view = camera.GetViewProjection();
glm::mat4 projection = glm::perspective(70.0f, (float)1600 / (float)1200, 0.1f, 1000.0f);
glUniformMatrix4fv(glGetUniformLocation(refShader.getProg(), "model"), 1, GL_FALSE, glm::value_ptr(model));
glUniformMatrix4fv(glGetUniformLocation(refShader.getProg(), "view"), 1, GL_FALSE, glm::value_ptr(view));
glUniformMatrix4fv(glGetUniformLocation(refShader.getProg(), "projection"), 1, GL_FALSE, glm::value_ptr(projection));
glUniform3f(glGetUniformLocation(refShader.getProg(), "cameraPos"), camera.getPos().x, camera.getPos().y, camera.getPos().z);
glActiveTexture(GL_TEXTURE3);
glUniform1i(glGetUniformLocation(refShader.getProg(), "skybox"), 3);
shader.Bind();
texture.Bind(0);
shader.Update(transformCube, camera);
cubeMesh.Draw();
glBindTexture(GL_TEXTURE_CUBE_MAP, skyboxTexture);
refShader.Bind();
refShader.Update(transform, camera);
sphereMesh.Draw();
This sequnece of operations is wrong:
glActiveTexture(GL_TEXTURE3);
glUniform1i(glGetUniformLocation(refShader.getProg(), "skybox"), 3);
shader.Bind();
Uniforms are per program state in the GL, and glUniform*() calls always affect the uniforms of the program currently in use. You seem to try to set this uniform before the program is bound, so it will fail, and the uniform in that program will still stay at the default value of 0.
I try to turn around my gui. I have projection:
glm::mat4 my_projection = glm::mat4( 2.0/static_cast<float>(m_window->getSize().x), 0.0, 0.0, -1.0,
0.0, 2.0/static_cast<float>(m_window->getSize().y), 0.0, -1.0,
0.0, 0.0, -1.0, 0.0,
0.0, 0.0, 0.0, 1.0);
And shader:
#version 330 core
in vec3 pos;
in vec2 UV;
in vec4 col;
uniform vec2 translation;
uniform mat4 my_projection;
out vec2 vecUV;
out vec4 vecColor;
void main()
{
vec3 tran_pos = vec3(pos + vec3(translation, 0.0f));
gl_Position = vec4(tran_pos, 1.0f) * my_projection;
vecUV = UV;
vecColor = col;
}
And I don't know how to turn around, when I change
m_window->getSize().x
to
-m_window->getSize().x
and
m_window->getSize().y
to
-m_window->getSize().y
everything disapear. How I can turn around this?
EDIT: (SOLUTION)
glm::mat4 my_projection = glm::ortho(0.0f, (float)m_window->getSize().x, (float)m_window->getSize().y, 0.0f);
// Shader:
#version 330 core
in vec3 pos;
in vec2 UV;
in vec4 col;
uniform vec2 translation;
uniform mat4 my_projection;
out vec2 vecUV;
out vec4 vecColor;
void main()
{
vec3 tran_pos = vec3(pos + vec3(translation, 0.0f));
gl_Position = my_projection * vec4(tran_pos, 1.0f);
vecUV = UV;
vecColor = col;
}
Just use glm function to matrix projection and multiply projection by position.