I've got this vertex shader:
#version 400
layout(location=0) in vec4 vertPosition;
layout(location=1) in vec2 vertUV;
layout(location=2) in vec3 vertNormal;
uniform mat4 MVP;
out vec3 fragPosition;
out vec2 fragUV;
out vec3 fragNormal;
void main(void){
gl_Position = MVP * vertPosition;
fragPosition = (MVP * vertPosition).rgb;
fragUV = vertUV;
fragNormal = (MVP * vec4(vertNormal,0)).rgb;
}
As soon as I'm multiplying vertPosition by MVP the object to render disappears, even if MVP is an identity matrix.
Here's the code where I'm setting MVP:
mat4 model = translate(mat4(), vec3(0,0,0));
mat4 view = translate(mat4(), vec3(0,0,-10));
mat4 proj = perspective(90.0f, (float)1280/720, 0.001f, 1000.0f);
mat4 MVP = model * view * proj;
GLint uniform_loc = glGetUniformLocation(this->_shaderID, "MVP");
glUniformMatrix4fv(uniform_loc, 1, GL_FALSE, value_ptr(matrix));
I tried different multiplication orders and multiplicating in the shader.
You've got the order in which you multiple MVP reversed. OpenGL matrix multiplication is column major right associative, hence it should be
mat4 MVP = proj * view * model;
A near clipping plane distance of 0.0001 is far too low. Essentially you're compressing all of the depth buffer resolution into a very small range. Make near as large as possible.
I don't get why you're selecting .rgb for the fragPosition and fragNormal.
From the look of your example you have forgotten to set the shader program before setting the uniform. Try using glUseProgram(this->program); (depending on where you've stored your program) before setting the matrix!
Related
I'm a new opengl programmer. I am plotting a height map composed of thousands of triangles in a 3D graph format. They are scaled so that they are plotted between -1 and +1 in the three axis. Now I am able to zoom in the X axis only and am able to translate in the X axis as well by applying the appropriate scale and translation matrices. This effectively allows me to zoom right into the data and move it in the x direction as I choose.
The problem is, once I zoom, the data in the x direction now extends outside the -1 to + 1 region which the boundaries of a graph. I want this data to not be shown.
How is this done in modern OpenGL?
Thank you
Edit:
The matrices are as follows:
plottingProgram["projection_matrix"].SetValue(Matrix4.CreatePerspectiveFieldOfView(0.45f, (float)width / height, 0.1f, 1000f));
plottingProgram["view_matrix"].SetValue(Matrix4.LookAt(new Vector3(0, 0, 10), Vector3.Zero, new Vector3(0, 1, 0)));
and the vertex shader is
public static string VertexShader = #"
#version 130
in vec3 vertexPosition;
out vec2 textureCoordinate;
uniform mat4 projection_matrix;
uniform mat4 view_matrix;
uniform mat4 model_matrix;
void main(void)
{
textureCoordinate = vertexPosition.xy;
gl_Position = projection_matrix * view_matrix * model_matrix * vec4(vertexPosition, 1);
}
";
Here is a link to the graph:
http://va2fsq.com/wp-content/uploads/graph.jpg
Thanks
I solved this. After trying many things like glScissor, I happened upon the glClip_distance. So my initial try placed a Uniform in the shader which was set to
in vec3 vertexPosition;
uniform vec4 plane0 = (-1,0,0,1);
uniform vec4 plane1 = (1,0,0,1);
void main(void)
{
gl_ClipDistance[0] = dot(vec4(vertexPosition,1), plane0;
gl_ClipDistance[1] = dot(vec4(vertexPosition,1), plane2;
Now the problem with this is that the vec4 planes are scaled and translated by any model matrix scaling or transformations. So that wouldn't work. So the solution is to move the clip vectors outside of the vertex shader and apply the opposite scaling to them as follows:
Vector4 clip1 = new Vector4(-1, 0, 0, 1.0f / scale);
Vector4 clip2 = new Vector4(1, 0, 0, 1.0f / scale);
plottingProgram["model_matrix"].SetValue(Matrix4.CreateScaling(new Vector3(scale,1,1)) * Matrix4.CreateTranslation(new Vector3(0,0,0)) *Matrix4.CreateRotationY(yangle) * Matrix4.CreateRotationX(xangle));
plottingProgram["plane0"].SetValue(clip1);
plottingProgram["plane1"].SetValue(clip2);
and the complete vertex shader is given by
public static string VertexShader = #"
#version 130
in vec3 vertexPosition;
out vec2 textureCoordinate;
uniform mat4 projection_matrix;
uniform mat4 view_matrix;
uniform mat4 model_matrix;
uniform vec4 plane0;
uniform vec4 plane1;
void main(void)
{
textureCoordinate = vertexPosition.xy;
gl_ClipDistance[0] = dot(vec4(vertexPosition,1), plane0);
gl_ClipDistance[1] = dot(vec4(vertexPosition,1), plane1);
gl_Position = projection_matrix * view_matrix * model_matrix * vec4(vertexPosition, 1);
}
";
You can also translate in the same way.
I am following this tutorial to create a skybox/cubemap with environmental mapping. I am having some trouble understanding a calculation in the vertex shader:
#version 330 core
layout (location = 0) in vec3 position;
layout (location = 1) in vec3 normal;
out vec3 Normal;
out vec3 Position;
uniform mat4 model;
uniform mat4 view;
uniform mat4 projection;
void main()
{
gl_Position = projection * view * model * vec4(position, 1.0f);
Normal = mat3(transpose(inverse(model))) * normal;
Position = vec3(model * vec4(position, 1.0f));
}
Here, the author is calculating the Normal before passing it to the fragment shader to calculate the reflection texture:
Normal = mat3(transpose(inverse(model))) * normal;
My question is, what exactly does this calculation do? Why do you have to calculate the transpose of the inverse of the model matrix before multiplying it with the normal?
If you don't do this, uneven scaling will distort the normal. I think this sums it up, with pictures, better than I possibly could: http://www.lighthouse3d.com/tutorials/glsl-12-tutorial/the-normal-matrix/
I'm doing per-pixel lighting(phong shading) on my terrain. I'm using a heightmap to generate the terrain height and then calculating the normal for each vertex. The normals are interpolated in the fragment shader and also normalized.
I am getting some weird dark lines near the edges of triangles where there shouldn't be.
http://imgur.com/L2kj4ca
I checked if the normals were correct using a geometry shader to draw the normals on the terrain and they seem to be correct.
http://imgur.com/FrJpdXI
There is no point using a normal map for the terrain it will just give pretty much the same normals. The problem lies with the way the normals are interpolated across a triangle.
I am out of idea's how to solve this. I couldn't find any working solution online.
Terrain Vertex Shader:
#version 330 core
layout (location = 0) in vec3 position;
layout (location = 1) in vec3 normal;
layout (location = 2) in vec2 textureCoords;
out vec2 pass_textureCoords;
out vec3 surfaceNormal;
out vec3 toLightVector;
out float visibility;
uniform mat4 transformationMatrix;
uniform mat4 viewMatrix;
uniform mat4 projectionMatrix;
uniform vec3 lightPosition;
const float density = 0.0035;
const float gradient = 5.0;
void main()
{
vec4 worldPosition = transformationMatrix * vec4(position, 1.0f);
vec4 positionRelativeToCam = viewMatrix * worldPosition;
gl_Position = projectionMatrix * positionRelativeToCam;
pass_textureCoords = textureCoords;
surfaceNormal = (transformationMatrix * vec4(normal, 0.0f)).xyz;
toLightVector = lightPosition - worldPosition.xyz;
float distance = length(positionRelativeToCam.xyz);
visibility = exp(-pow((distance * density), gradient));
visibility = clamp(visibility, 0.0, 1.0);
}
Terrain Fragment Shader:
#version 330 core
in vec2 pass_textureCoords;
in vec3 surfaceNormal;
in vec3 toLightVector;
in float visibility;
out vec4 colour;
uniform vec3 lightColour;
uniform vec3 fogColour;
uniform sampler2DArray blendMap;
uniform sampler2DArray diffuseMap;
void main()
{
vec4 blendMapColour = texture(blendMap, vec3(pass_textureCoords, 0));
float backTextureAmount = 1 - (blendMapColour.r + blendMapColour.g + blendMapColour.b);
vec2 tiledCoords = pass_textureCoords * 255.0;
vec4 backgroundTextureColour = texture(diffuseMap, vec3(tiledCoords, 0)) * backTextureAmount;
vec4 rTextureColour = texture(diffuseMap, vec3(tiledCoords, 1)) * blendMapColour.r;
vec4 gTextureColour = texture(diffuseMap, vec3(tiledCoords, 2)) * blendMapColour.g;
vec4 bTextureColour = texture(diffuseMap, vec3(tiledCoords, 3)) * blendMapColour.b;
vec4 diffuseColour = backgroundTextureColour + rTextureColour + gTextureColour + bTextureColour;
vec3 unitSurfaceNormal = normalize(surfaceNormal);
vec3 unitToLightVector = normalize(toLightVector);
float brightness = dot(unitSurfaceNormal, unitToLightVector);
float ambient = 0.2;
brightness = max(brightness, ambient);
vec3 diffuse = brightness * lightColour;
colour = vec4(diffuse, 1.0) * diffuseColour;
colour = mix(vec4(fogColour, 1.0), colour, visibility);
}
This can be either two issues :
1. Incorrect normals :
There is different types of shading : Flat shading, Gouraud shading and Phong shading (different of Phong specular) example :
You usually want to do a Phong shading. To do that, OpenGL make your life easier and interpolate for you the normals between each vertex of each triangle, so at each pixel you have the correct normal for this point: but you still need to feed it proper normal values, that are the average of the normals of every triangles attached to this vertex. So in your function that create the vertex, the normals and the UVs, you need to compute the normal at each vertex by averaging every triangle normal attached to this vertex. illustration
2. Subdivision problem :
The other possible issue is that your terrain is not subdivided enough, or your heightmap resolution is too low, resulting to this kind of glitch because of the difference of height between two vertex in one triangle (so between two pixels in your heightmap).
Maybe if you can provide some of your code and shaders, maybe even the heightmap so we can pin exactly what is happening in your case.
This is old, but I suspect you're not transforming your normal using the transposed inverse of the upper 3x3 part of your modelview matrix. See this. Not sure what's in "transformationMatrix", but if you're using it to transform the vertex and the normal something is probably fishy...
I'm working on a normal mapping implementation for a tutorial and for teaching purposes I'd like to pass a TBN matrix to the fragment shader (from the vertex shader) so I can transform normal vectors in tangent space to world-space for lighting calculations. The normal mapping is applied to a 2D plane with its normal pointing in the positive z direction.
However, when I calculate the TBN matrix in the vertex shader of a flat plane (so all tangents/bitangents are the same for all vertices) the displayed normals are completely off. While if I pass the tangent/bitangent and normal vectors to the fragment shader and construct the TBN there, it works just fine as the image below shows (with displayed normals):
This is where it gets weird. Because the plane is flat, the T,B and N vectors are the same for all its vertices thus the TBN matrix should also be the same for each fragment (as fragment interpolation doesn't change anything). The TBN matrix in the vertex shader should be exactly the same as the TBN matrix in the fragment shader but the visual outputs say otherwise.
The source code of both the vertex and fragment shader are below:
Vertex:
#version 330 core
layout (location = 0) in vec3 position;
layout (location = 1) in vec3 normal;
layout (location = 2) in vec2 texCoords;
layout (location = 3) in vec3 tangent;
layout (location = 4) in vec3 bitangent;
out VS_OUT {
vec3 FragPos;
vec3 Normal;
vec2 TexCoords;
vec3 Tangent;
vec3 Bitangent;
mat3 TBN;
} vs_out;
uniform mat4 projection;
uniform mat4 view;
uniform mat4 model;
void main()
{
gl_Position = projection * view * model * vec4(position, 1.0f);
vs_out.FragPos = vec3(model * vec4(position, 1.0));
vs_out.TexCoords = texCoords;
mat3 normalMatrix = transpose(inverse(mat3(model)));
vs_out.Normal = normalize(normalMatrix * normal);
vec3 T = normalize(normalMatrix * tangent);
vec3 B = normalize(normalMatrix * bitangent);
vec3 N = normalize(normalMatrix * normal);
vs_out.TBN = mat3(T, B, N);
vs_out.Tangent = T;
vs_out.Bitangent = B;
}
Fragment
#version 330 core
out vec4 FragColor;
in VS_OUT {
vec3 FragPos;
vec3 Normal;
vec2 TexCoords;
vec3 Tangent;
vec3 Bitangent;
mat3 TBN;
} fs_in;
uniform sampler2D diffuseMap;
uniform sampler2D normalMap;
uniform vec3 lightPos;
uniform vec3 viewPos;
uniform bool normalMapping;
void main()
{
vec3 normal = fs_in.Normal;
mat3 tbn;
if(normalMapping)
{
// Obtain normal from normal map in range [0,1]
normal = texture(normalMap, fs_in.TexCoords).rgb;
// Transform normal vector to range [-1,1]
normal = normalize(normal * 2.0 - 1.0);
// Then transform normal in tangent space to world-space via TBN matrix
tbn = mat3(fs_in.Tangent, fs_in.Bitangent, fs_in.Normal); // TBN calculated in fragment shader
// normal = normalize(tbn * normal); // This works!
normal = normalize(fs_in.TBN * normal); // This gives incorrect results
}
// Get diffuse color
vec3 color = texture(diffuseMap, fs_in.TexCoords).rgb;
// Ambient
vec3 ambient = 0.1 * color;
// Diffuse
vec3 lightDir = normalize(lightPos - fs_in.FragPos);
float diff = max(dot(lightDir, normal), 0.0);
vec3 diffuse = diff * color;
// Specular
vec3 viewDir = normalize(viewPos - fs_in.FragPos);
vec3 reflectDir = reflect(-lightDir, normal);
vec3 halfwayDir = normalize(lightDir + viewDir);
float spec = pow(max(dot(normal, halfwayDir), 0.0), 32.0);
vec3 specular = vec3(0.2) * spec; // assuming bright white light color
FragColor = vec4(ambient + diffuse + specular, 1.0f);
FragColor = vec4(normal, 1.0); // display normals for debugging
}
Both TBN matrices are clearly different. Below I compiled an image of different fragment shader outputs:
You can see that the T,B and N vectors are correct and so is the fragment shader's tbn matrix, but the TBN matrix from the vertex shader fs_in.TBN gives completely bogus values.
I am completely clueless as to why it doesn't work. I know I can simply pass the Tangent and Bitangent vector to the fragment shader, calculate it there and be done with it but I'm quite curious as to the exact reason why this doesn't work?
Some general remarks:
1) You should normalize fs_in.Tangent, fs_in.Bitangent, and fs_in.Normal in the fragment shader, since it is not guaranteed that they are after the varying interpolation. They should be normalized, because they are the basis vectors of a coordinate system.
2) You don't need to pass all three, tangent, bitangent, and normal, since one of them can be calculated using the cross product: bitangent = cross(tangent, normal). This point also speaks in favor of passing (two) vectors instead of the whole matrix.
To your question, why fs_in.TBN does not look like tbn in the fragment shader:
The images you provide look very strange, indeed. Looks like the matrix' vectors are somehow mixed up. Which output do you get, displaying the transposed matrix transpose(fs_in.TBN)?
Also make sure that the matrix' columns are accessed correctly like described in [1]! (It looks like they are, but please double check, you never know.)
[1] Geeks3D; GLSL 4×4 Matrix Fields; http://www.geeks3d.com/20141114/glsl-4x4-matrix-mat4-fields/
Edit:
Alright got it now :D
Problem: Completly forgot glm uses colum-major matrices. Just had to change GL_TRUE, to GL_FALSE and everything is alright.
I try to compute my ModelMatrix with my ProjectionMatrix. Like so:
#version 330
layout(location = 0) in vec4 position;
layout(location = 1) in vec4 color;
uniform mat4 projectionMatrix; //This are the Matrixes from my cpp-app
uniform mat4 modelMatrix; //With a debugger that can show all active uniforms i checked their values: They're right!
uniform mat4 testUni; //Here I checked if its working when I precompute the model and perspective matrices in my source: works
mat4 viewMatrix = mat4(1.0f);
noperspective out vec4 vertColor;
mat4 MVP = projectionMatrix * modelMatrix ; //Should actually have the same value like testUni
void main()
{
gl_Position = testUni * position ; //Well... :) Works
gl_Position = MVP * position ; //Well... :) Doesn't work [Just the perspective Transforn]
vertColor = position;
}
Move the statement
mat4 MVP = projectionMatrix * modelMatrix ; //Should actually have the same value like testUni
into main(). Shader execution starts at main. If you want to avoid per-vertex computations, precompute the matrix outside and supply it as a uniform.