I've, the last month, been following tutorials on a various pages (learnopengl.com) amongst others.
I got to the lighting section (I created a loader to load meshes with Assimp first), my fragmentshader code is pretty much the same as the tutorials lighting ( learnopengl.com/basic_lighting).
Frag code:
#version 130
out vec4 outColor;
in vec3 fragPos;
in vec3 normal;
in vec2 texcoord;
uniform sampler2D tex;
uniform vec3 lightPos;
uniform vec3 lightColor;
void main(){
float ambientStrength = 0.1f;
vec3 ambient = ambientStrength * lightColor;
//Diffuse
vec3 norm = normalize(normal);
vec3 lightDir = normalize(lightPos - fragPos);
float diff = max(dot(norm, lightDir), 0.0f);
vec3 diffuse = diff * lightColor;
float objectColor = 0.5f;
//texture(tex, texcoord)
vec3 result = (ambient + diffuse) * objectColor;
outColor = vec4(result, 1.0f);
}
When, for example, lighting a plane it gives me these results:
When I'm not lighting the plane it's plain grey.
Here's the .obj file or the plane:
Blender v2.69 (sub 0) OBJ File: 'plane.blend'
# www.blender.org
mtllib plane.mtl
o Plane
v 10.000000 0.000000 10.000000
v -10.000000 0.000000 10.000000
v 10.000000 0.000000 -10.000000
v -10.000000 0.000000 -10.000000
vn 0.000000 1.000000 0.000000
usemtl None
s off
f 2//1 1//1 3//1
f 4//1 2//1 3//1
It get's imported correctly, every vertex normal is { 0, 1, 0} and the indices are also correct.
When searching for things like "OpenGL light disortions" or just "OpenGL lighting" I can't find anything like this. So I really have no idea what's wrong.
Oh yeah, I use openGL 3.3, and I have an integrated intel GPU.
CPU is intel core i3-2367M in case there is a problem with the hardware.
Thank you for your time :D
EDIT:
So I just tried to show the color of my normals on the plane, they should be solid green but they are this abomination:
I'll also dump my vertexshadercode in here:
#version 130
in vec3 position;
in vec3 normal;
in vec2 texCoord;
out vec3 fragPos;
out vec3 Normal;
out vec2 texcoord;
uniform mat4 transform;
uniform mat4 view;
uniform mat4 projection;
void main(){
texcoord = texCoord;
Normal = normal;
fragPos = vec3(transform * vec4(position, 1.0f));
gl_Position = projection * view * transform * vec4(position, 1.0);
}
Here's how I set up my mesh:
void mesh::bindVertices(){
glBindVertexArray(vertexArrayObject);
glBindBuffer(GL_ARRAY_BUFFER, vertexBuffer);
glBufferData(GL_ARRAY_BUFFER, this->vertices.size() * sizeof(Vertex), &vertices[0], GL_STATIC_DRAW);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, elementBuffer);
glBufferData(GL_ELEMENT_ARRAY_BUFFER, this->indices.size() * sizeof(GLuint), &indices[0], GL_STATIC_DRAW);
glEnableVertexAttribArray(0);
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, sizeof(Vertex), (GLvoid*)0); // Position
glEnableVertexAttribArray(1);
glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, sizeof(Vertex), (GLvoid*)offsetof(Vertex, normal)); //Normal
glEnableVertexAttribArray(2);
glVertexAttribPointer(2, 2, GL_FLOAT, GL_FALSE, sizeof(Vertex), (GLvoid*)offsetof(Vertex, texCoord)); //Texcoord
glBindVertexArray(0);
}
Vertex.h
#ifndef VERTEX_H
#define VERTEX_H
#include <vector>
#include <glm/glm.hpp>
class Vertex
{
public:
Vertex(){
position = glm::vec3(0.0f, 0.0f, 0.0f);
normal = glm::vec3(0.0f, 0.0f, 0.0f);
texCoord = glm::vec2(0.0f, 0.0f);
};
Vertex(glm::vec3 pos, glm::vec3 nor, glm::vec2 tex){
setUpVertex(pos, nor, tex);
};
~Vertex(){}
void setUpVertex(glm::vec3 pos, glm::vec3 nor, glm::vec2 tex){
this->position = pos;
this->normal = nor;
this->texCoord = tex;
};
void print(){
std::cout << "Position: { " << position.x << ", " << position.y << ", " << position.z << " }\n";
std::cout << "Normals: { " << normal.x << ", " << normal.y << ", " << normal.z << " }\n";
std::cout << "Texture Coordinates: { " << texCoord.x << ", " << texCoord.y << " }" << std::endl;
}
glm::vec3 position;
glm::vec3 normal;
glm::vec2 texCoord;
protected:
private:
};
#endif // VERTEX_H
The print function is there for debugging, and it outputs the correct values, so I really have no idea what is going on.
One thing that is not a problem is loading in the model is what I've managed to gather and the normals are behaving very strangley.
You don't correctly pass your normal data from the vertex shader to the fragment shader. You use out vec3 Normal in the VS, but in vec3 normal (note the lowercase) in the FS, so your input value is just undefined.
Related
I have this vertex shader, which simply passes the position given and passes the UV and color to the fragment shader:
#version 330 core
layout (location = 0) in vec2 in_pos;
layout (location = 1) in vec2 in_texUV;
layout (location = 2) in vec4 in_color;
out vec2 ex_texUV;
out vec4 ex_color;
uniform mat4 projection;
void main()
{
gl_Position = vec4(in_pos, 0.0, 1.0) * projection;
ex_texUV = in_texUV;
ex_color = in_color;
}
Edit: The fragment shader is shown here, and all uniforms are properly set:
#version 330 core
in vec2 in_texUV;
in vec4 in_color;
out vec4 out_color;
uniform vec2 screenSize;
uniform vec3 transparentColour;
uniform sampler2D sprite;
uniform sampler2D palette;
uniform int paletteLines[0x100];
void main()
{
if (in_color.a == 0.0) {
vec4 coord = gl_FragCoord - 0.5;
vec2 screenPos;
screenPos.x = coord.x * screenSize.x;
screenPos.y = coord.y * screenSize.y;
int id = paletteLines[int(screenPos.y)];
int index = int(texture2D(sprite, in_texUV).r * 255);
if (index == 0)
discard;
vec2 palvec;
palvec.x = index;
palvec.y = id;
out_color = texture(palette, palvec);
}
}
(The projection variable is properly set, shown using NVIDIA Nsight.)
Both the vertex and fragment shader have been edited to be simple passthroughs (even setting the fragment shader to a constant vec4(1.0, 1.0, 1.0, 1.0),) but it's always shown nothing.
To setup for the shader, I first set up the VAO and VBO to pass from a list of DrawVertex:
glGenVertexArrays(1, &VAO);
glBindVertexArray(VAO);
glGenBuffers(2, &GFXVBO);
glBindBuffer(GL_ARRAY_BUFFER, GFXVBO);
glVertexAttribPointer(0, 2, GL_SHORT, GL_FALSE, sizeof(DrawVertex), 0);
glEnableVertexAttribArray(0);
glVertexAttribPointer(1, 2, GL_SHORT, GL_FALSE, sizeof(DrawVertex), (void *)(sizeof(short) * 2));
glEnableVertexAttribArray(1);
glVertexAttribPointer(2, 4, GL_UNSIGNED_BYTE, GL_FALSE, sizeof(DrawVertex), (void *)(sizeof(short) * 4));
glEnableVertexAttribArray(2);
and then draw using the code below (the VAO and VBO are ensured to be bound, and gfxShader is just a helper to use a program):
gfxShader.use();
// [setup the program, change uniforms as necessary]
// lastRenderCount is how many to render
// gfxPolyList is the list of DrawVertex
glBufferData(GL_ARRAY_BUFFER, lastRenderCount * sizeof(DrawVertex), gfxPolyList, GL_DYNAMIC_DRAW);
glDrawArrays(GL_TRIANGLES, 0, lastRenderCount);
gfxShader.stop();
However, despite this, although RenderDoc shows that the input is being passed through, the output shows nothing at all. On top of this, NVIDIA Nsight says that no fragments are being drawn. Where could I be going wrong?
For context, here is struct DrawVertex:
struct DrawVertex {
short x;
short y;
short u;
short v;
Color color = 0; //0xRRGGBBAA
};
gl_Position = vec4(in_pos, 0.0, 1.0) * projection;
This is wrong. Matrix multiplication is not commutative. Should be:
gl_Position = projection * vec4(in_pos, 0.0, 1.0);
If you don't believe me, try this:
glm::mat4 proj = {
1.0f, 0.0f, 3.0f, 5.0f,
0.0f, 1.0f, 3.0f, 6.0f,
0.0f, 0.0f, 1.0f, 0.0f,
0.0f, 0.0f, 3.0f, 1.0f
};
glm::vec4 vec = { 0.0f, 1.0f, 0.0f, 1.0f };
glm::vec4 result1 = proj * vec;
glm::vec4 result2 = vec * proj;
std::cout << "result1: " << result1.x << result1.y << result1.z << result1.w << '\n';
std::cout << "result2: " << result2.x << result2.y << result2.z << result2.w << '\n';
// Output:
result1: 0167
result2: 5701
https://learnopengl.com/Getting-started/Transformations
Edit: Your fragment shader runs only if in_color.a == 0.0? Are you sure this is correct? Maybe you meant to use != instead.
Although I call glEnableVertexAttribArray and glVertexAttribPointer, my vertex shader cannot seem to access the value (I say value because i am not sure what it is called, Attribute?).
I am confused as I have other values that the vertex shader can access by doing exactly the same thing.
In the following code the Vertex position in attribute position 0 and the Vertex normal in attribute position 1 can be accessed fine by the shader however when I use the Vertex color value in attribute position 2 as the color for my mesh it is black even if set otherwise.
//Vertex Position
glEnableVertexAttribArray(0);
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, sizeof(Vertex), (void*)offsetof(Vertex, vertexPosition));
//Vertex Normal
glEnableVertexAttribArray(1);
glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, sizeof(Vertex), (void*)offsetof(Vertex, vertexNormal));
//Vertex Colour
glEnableVertexAttribArray(2);
glVertexAttribPointer(2, 3, GL_FLOAT, GL_FALSE, sizeof(Vertex), (void*)offsetof(Vertex, vertexColor));
Here is the Vertex struct
struct Vertex {
glm::vec3 vertexPosition;
glm::vec3 vertexNormal;
glm::vec3 vertexColor;
glm::vec2 textureCoords;
glm::vec3 vertexTangent;
glm::vec3 vertexBitangent;
Vertex() {}
Vertex(glm::vec3 vertexPosition, glm::vec3 vertexNormal = glm::vec3(0), glm::vec3 vertexColor = glm::vec3(0), glm::vec2 textureCoords = glm::vec2(0)) {
this->vertexPosition = vertexPosition;
this->vertexNormal = vertexNormal;
this->textureCoords = textureCoords;
}
};
Here is the Shader code. If I uncomment the commented line the mesh renders red as expected
#version 330 core
uniform mat4 uModelMatrix;
uniform mat4 uViewMatrix;
uniform mat4 uProjectionMatrix;
uniform vec3 uLightPosition;
layout(location = 0) in vec3 aVertexPosition;
layout(location = 1) in vec3 aVertexNormal;
layout(location = 2) in vec3 aVertexColor;
out vec3 viewDirection;
out vec3 lightPosition;
out vec3 fragmentPosition;
out vec3 materialColor;
flat out vec3 fragmentNormal;
void main(){
materialColor = aVertexColor;
//materialColor = vec3(0.5, 0, 0);
mat4 modelViewMatrix = uViewMatrix * uModelMatrix;
vec3 viewSpacePosition = (modelViewMatrix * vec4(aVertexPosition, 1)).xyz;
viewDirection = normalize(viewSpacePosition);
vec3 viewSpaceNormal = normalize(modelViewMatrix * vec4(aVertexNormal, 0)).xyz;
fragmentNormal = viewSpaceNormal;
fragmentNormal = aVertexNormal;
lightPosition = uLightPosition;
fragmentPosition = vec3(uModelMatrix * vec4(aVertexPosition, 1.0));
gl_Position = uProjectionMatrix * modelViewMatrix * vec4(aVertexPosition, 1);
}
Even if vertexColor defaults to glm::vec3(1) instead of glm::vec3(0) it is still black. I have checked the values for vertexColor before drawing with the shader and the color is not black.
It looks like you are not setting your vertexColor value in the Vertex constructor.
Vertex(glm::vec3 vertexPosition, glm::vec3 vertexNormal = glm::vec3(0), glm::vec3 vertexColor = glm::vec3(0), glm::vec2 textureCoords = glm::vec2(0)) {
this->vertexPosition = vertexPosition;
this->vertexNormal = vertexNormal;
this->vertexColor = vertexColor;
}
I am trying to incorporate both normal mapping & cube mapping into a single program, but I am having trouble getting them to render correctly. I am working on a simple exercise to help me with that before going onto something more complexed. I am trying to render both these objects into a single program. They both have different textures and the torus uses cube mapping while the wall uses normal mapping.
These are what they are supposed to look like individually:
Currently, this is what I've got. The torus renders correctly but the wall's textures don't appear.
I am using 2 separate shader programs for this, and it is my first time using more than 1 shader program, for a program. I suspect my issue could be with the initialising of shader variables, or something really obvious that I'm just not getting. I am using two different Vertex structs for the objects.
struct Vertex2
{
GLfloat position[3];
GLfloat normal[3];
GLfloat tangent[3];
GLfloat texCoord[2];
};
Vertex2 g_vertices[] = {
// Front: triangle 1
// vertex 1
-1.0f, 1.0f, 0.0f, // position
0.0f, 0.0f, 1.0f, // normal
1.0f, 0.0f, 0.0f, // tangent
0.0f, 1.0f, // texture coordinate
// vertex 2
-1.0f, -1.0f, 0.0f, // position
0.0f, 0.0f, 1.0f, // normal
1.0f, 0.0f, 0.0f, // tangent
0.0f, 0.0f, // texture coordinate
// vertex 3
1.0f, 1.0f, 0.0f, // position
0.0f, 0.0f, 1.0f, // normal
1.0f, 0.0f, 0.0f, // tangent
1.0f, 1.0f, // texture coordinate
// triangle 2
// vertex 1
1.0f, 1.0f, 0.0f, // position
0.0f, 0.0f, 1.0f, // normal
1.0f, 0.0f, 0.0f, // tangent
1.0f, 1.0f, // texture coordinate
// vertex 2
-1.0f, -1.0f, 0.0f, // position
0.0f, 0.0f, 1.0f, // normal
1.0f, 0.0f, 0.0f, // tangent
0.0f, 0.0f, // texture coordinate
// vertex 3
1.0f, -1.0f, 0.0f, // position
0.0f, 0.0f, 1.0f, // normal
1.0f, 0.0f, 0.0f, // tangent
1.0f, 0.0f, // texture coordinate
};
Main.cpp init function:
static void init(GLFWwindow* window)
{
glEnable(GL_DEPTH_TEST); // enable depth buffer test
glEnable(GL_TEXTURE_2D);
// read the image data
GLint imageWidth[5]; //image width info
GLint imageHeight[5]; //image height info
g_texImage[FRONT] = readBitmapRGBImage("images/cm_front.bmp", &imageWidth[0], &imageHeight[0]);
g_texImage[BACK] = readBitmapRGBImage("images/cm_back.bmp", &imageWidth[0], &imageHeight[0]);
g_texImage[LEFT] = readBitmapRGBImage("images/cm_left.bmp", &imageWidth[0], &imageHeight[0]);
g_texImage[RIGHT] = readBitmapRGBImage("images/cm_right.bmp", &imageWidth[0], &imageHeight[0]);
g_texImage[TOP] = readBitmapRGBImage("images/cm_top.bmp", &imageWidth[0], &imageHeight[0]);
g_texImage[BOTTOM] = readBitmapRGBImage("images/cm_bottom.bmp", &imageWidth[0], &imageHeight[0]);
g_texImage[6] = readBitmapRGBImage("images/Fieldstone.bmp", &imageWidth[1], &imageHeight[1]);
g_texImage[7] = readBitmapRGBImage("images/FieldstoneBumpDOT3.bmp", &imageWidth[2], &imageHeight[2]);
glGenTextures(10, g_textureID);
// ...
// create and compile our GLSL program from the shader files
g_shaderProgramID[0] = loadShaders("CubeEnvMapVS.vert", "CubeEnvMapFS.frag");
g_shaderProgramID[1] = loadShaders("NormalMappingVS.vert", "NormalMappingFS.frag");
// find the location of shader variables
for (int i = 0; i < 2; i++)
{
positionIndex[i] = glGetAttribLocation(g_shaderProgramID[i], "aPosition");
normalIndex[i] = glGetAttribLocation(g_shaderProgramID[i], "aNormal");
texCoordIndex[i] = glGetAttribLocation(g_shaderProgramID[i], "aTexCoord");
g_MVP_Index[i] = glGetUniformLocation(g_shaderProgramID[i], "uModelViewProjectionMatrix");
g_M_Index[i] = glGetUniformLocation(g_shaderProgramID[i], "uModelMatrix");
g_viewPointIndex[i] = glGetUniformLocation(g_shaderProgramID[i], "uViewPoint");
g_lightPositionIndex[i] = glGetUniformLocation(g_shaderProgramID[i], "uLightingProperties.position");
g_lightAmbientIndex[i] = glGetUniformLocation(g_shaderProgramID[i], "uLightingProperties.ambient");
g_lightDiffuseIndex[i] = glGetUniformLocation(g_shaderProgramID[i], "uLightingProperties.diffuse");
g_lightSpecularIndex[i] = glGetUniformLocation(g_shaderProgramID[i], "uLightingProperties.specular");
g_lightShininessIndex[i] = glGetUniformLocation(g_shaderProgramID[i], "uLightingProperties.shininess");
g_materialAmbientIndex[i] = glGetUniformLocation(g_shaderProgramID[i], "uMaterialProperties.ambient");
g_materialDiffuseIndex[i] = glGetUniformLocation(g_shaderProgramID[i], "uMaterialProperties.diffuse");
g_materialSpecularIndex[i] = glGetUniformLocation(g_shaderProgramID[i], "uMaterialProperties.specular");
}
g_envMapSamplerIndex = glGetUniformLocation(g_shaderProgramID[0], "uEnvironmentMap");
tangentIndex = glGetAttribLocation(g_shaderProgramID[1], "aTangent");
g_texSamplerIndex = glGetUniformLocation(g_shaderProgramID[1], "uTextureSampler");
g_normalSamplerIndex = glGetUniformLocation(g_shaderProgramID[1], "uNormalSampler");
// initialise model matrix to the identity matrix
g_mm_torus = glm::mat4(1.0f);
g_mm_wall = mat4(1.0f);
// ...
// load mesh
// load_mesh("models/sphere.obj");
load_mesh("models/torus.obj");
// ...
// generate identifier for VBOs and copy data to GPU
glGenBuffers(5, g_VBO);
glBindBuffer(GL_ARRAY_BUFFER, g_VBO[0]);
glBufferData(GL_ARRAY_BUFFER, sizeof(Vertex)*g_numberOfVertices, g_pMeshVertices, GL_STATIC_DRAW);
// generate identifier for IBO and copy data to GPU
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, g_VBO[1]);
glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(GLint) * 3 * g_numberOfFaces, g_pMeshIndices, GL_STATIC_DRAW);
// generate identifiers for VAO
glGenVertexArrays(5, g_VAO);
// create VAO and specify VBO data
glBindVertexArray(g_VAO[0]);
glBindBuffer(GL_ARRAY_BUFFER, g_VBO[0]);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, g_VBO[1]);
glVertexAttribPointer(positionIndex[0], 3, GL_FLOAT, GL_FALSE, sizeof(Vertex), reinterpret_cast<void*>(offsetof(Vertex, position)));
glVertexAttribPointer(normalIndex[0], 3, GL_FLOAT, GL_FALSE, sizeof(Vertex), reinterpret_cast<void*>(offsetof(Vertex, normal)));
glEnableVertexAttribArray(positionIndex[0]); // enable vertex attributes
glEnableVertexAttribArray(normalIndex[0]);
// generate identifier for VBOs and copy data to GPU
glBindBuffer(GL_ARRAY_BUFFER, g_VBO[2]);
glBufferData(GL_ARRAY_BUFFER, sizeof(g_vertices), g_vertices, GL_STATIC_DRAW);
// create VAO and specify VBO data
glBindVertexArray(g_VAO[1]);
glBindBuffer(GL_ARRAY_BUFFER, g_VBO[2]);
glVertexAttribPointer(positionIndex[1], 3, GL_FLOAT, GL_FALSE, sizeof(Vertex2), reinterpret_cast<void*>(offsetof(Vertex2, position)));
glVertexAttribPointer(normalIndex[1], 3, GL_FLOAT, GL_FALSE, sizeof(Vertex2), reinterpret_cast<void*>(offsetof(Vertex2, normal)));
glVertexAttribPointer(tangentIndex, 3, GL_FLOAT, GL_FALSE, sizeof(Vertex2), reinterpret_cast<void*>(offsetof(Vertex2, tangent)));
glVertexAttribPointer(texCoordIndex[0], 2, GL_FLOAT, GL_FALSE, sizeof(Vertex2), reinterpret_cast<void*>(offsetof(Vertex2, texCoord)));
// enable vertex attributes
glEnableVertexAttribArray(positionIndex[1]);
glEnableVertexAttribArray(normalIndex[1]);
glEnableVertexAttribArray(tangentIndex);
glEnableVertexAttribArray(texCoordIndex[0]);
}
Render scene function:
static void render_scene()
{
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); // clear colour buffer and depth buffer
glUseProgram(g_shaderProgramID[0]); // use the shaders associated with the shader program
glBindVertexArray(g_VAO[0]); // make VAO active
// set uniform shader variables
glm::mat4 MVP = g_camera.getProjectionMatrix() * g_camera.getViewMatrix() * g_mm_torus;
glUniformMatrix4fv(g_MVP_Index[0], 1, GL_FALSE, &MVP[0][0]);
glUniformMatrix4fv(g_M_Index[0], 1, GL_FALSE, &g_mm_torus[0][0]);
glUniform3fv(g_viewPointIndex[0], 1, &g_camera.getPosition()[0]);
glUniform4fv(g_lightPositionIndex[0], 1, &g_lightProperties.position[0]);
glUniform4fv(g_lightAmbientIndex[0], 1, &g_lightProperties.ambient[0]);
glUniform4fv(g_lightDiffuseIndex[0], 1, &g_lightProperties.diffuse[0]);
glUniform4fv(g_lightSpecularIndex[0], 1, &g_lightProperties.specular[0]);
glUniform1fv(g_lightShininessIndex[0], 1, &g_lightProperties.shininess);
glUniform4fv(g_materialAmbientIndex[0], 1, &g_materialProperties.ambient[0]);
glUniform4fv(g_materialDiffuseIndex[0], 1, &g_materialProperties.diffuse[0]);
glUniform4fv(g_materialSpecularIndex[0], 1, &g_materialProperties.specular[0]);
glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_CUBE_MAP, g_textureID[0]);
glUniform1i(g_envMapSamplerIndex, 0);
glDrawElements(GL_TRIANGLES, g_numberOfFaces * 3, GL_UNSIGNED_INT, 0); // display the vertices based on their indices and primitive type
glUseProgram(g_shaderProgramID[1]); // use the shaders associated with the shader program
glBindVertexArray(g_VAO[1]); // make VAO active
// set uniform shader variables
glClear(GL_DEPTH_BUFFER_BIT);
MVP = g_camera.getProjectionMatrix() * g_camera.getViewMatrix() * g_mm_wall;
glUniformMatrix4fv(g_MVP_Index[1], 1, GL_FALSE, &MVP[0][0]);
glUniformMatrix4fv(g_M_Index[1], 1, GL_FALSE, &g_mm_wall[0][0]);
glUniform3fv(g_viewPointIndex[1], 1, &g_camera.getPosition()[0]);
glUniform4fv(g_lightPositionIndex[1], 1, &g_lightProperties.position[0]);
glUniform4fv(g_lightAmbientIndex[1], 1, &g_lightProperties.ambient[0]);
glUniform4fv(g_lightDiffuseIndex[1], 1, &g_lightProperties.diffuse[0]);
glUniform4fv(g_lightSpecularIndex[1], 1, &g_lightProperties.specular[0]);
glUniform1fv(g_lightShininessIndex[1], 1, &g_lightProperties.shininess);
glUniform4fv(g_materialAmbientIndex[1], 1, &g_materialProperties.ambient[0]);
glUniform4fv(g_materialDiffuseIndex[1], 1, &g_materialProperties.diffuse[0]);
glUniform4fv(g_materialSpecularIndex[1], 1, &g_materialProperties.specular[0]);
glActiveTexture(GL_TEXTURE1);
glBindTexture(GL_TEXTURE_2D, g_textureID[6]);
glActiveTexture(GL_TEXTURE2);
glBindTexture(GL_TEXTURE_2D, g_textureID[7]);
glUniform1i(g_texSamplerIndex, 1);
glUniform1i(g_normalSamplerIndex, 2);
glDrawArrays(GL_TRIANGLES, 0, 36);
glFlush(); // flush the pipeline
}
Vertex shader for torus:
#version 330 core
// input data (different for all executions of this shader)
in vec3 aPosition;
in vec3 aNormal;
// uniform input data
uniform mat4 uModelViewProjectionMatrix;
uniform mat4 uModelMatrix;
// output data (will be interpolated for each fragment)
out vec3 vNormal;
out vec3 vPosition;
void main()
{
// set vertex position
gl_Position = uModelViewProjectionMatrix * vec4(aPosition, 1.0);
// world space
vPosition = (uModelMatrix * vec4(aPosition, 1.0)).xyz;
vNormal = (uModelMatrix * vec4(aNormal, 0.0)).xyz;
}
Fragment shader for torus:
#version 330 core
// interpolated values from the vertex shaders
in vec3 vNormal;
in vec3 vPosition;
// uniform input data
struct LightProperties
{
vec4 position;
vec4 ambient;
vec4 diffuse;
vec4 specular;
float shininess;
};
struct MaterialProperties
{
vec4 ambient;
vec4 diffuse;
vec4 specular;
};
uniform LightProperties uLightingProperties;
uniform MaterialProperties uMaterialProperties;
uniform vec3 uViewPoint;
uniform samplerCube uEnvironmentMap;
// output data
out vec3 fColor;
void main()
{
vec3 N = normalize(vNormal);
vec3 L;
// determine whether the light is a point light source or directional light
if(uLightingProperties.position.w == 0.0f)
L = normalize((uLightingProperties.position).xyz);
else
L = normalize((uLightingProperties.position).xyz - vPosition);
vec3 V = normalize(uViewPoint - vPosition);
vec3 R = reflect(-L, N);
// calculate the ambient, diffuse and specular components
vec4 ambient = uLightingProperties.ambient * uMaterialProperties.ambient;
vec4 diffuse = uLightingProperties.diffuse * uMaterialProperties.diffuse * max(dot(L, N), 0.0);
vec4 specular = vec4(0.0f, 0.0f, 0.0f, 1.0f);
if(dot(L, N) > 0.0f)
{
specular = uLightingProperties.specular * uMaterialProperties.specular
* pow(max(dot(V, R), 0.0), uLightingProperties.shininess);
}
vec3 reflectEnvMap = reflect(-V, N);
// set output color
fColor = texture(uEnvironmentMap, reflectEnvMap).rgb;
fColor *= (diffuse + specular + ambient).rgb;
}
Vertex shader for wall:
#version 330 core
// input data (different for all executions of this shader)
in vec3 aPosition;
in vec3 aNormal;
in vec3 aTangent;
in vec2 aTexCoord;
// uniform input data
uniform mat4 uModelViewProjectionMatrix;
uniform mat4 uModelMatrix;
// output data (will be interpolated for each fragment)
out vec3 vPosition;
out vec3 vNormal;
out vec3 vTangent;
out vec2 vTexCoord;
void main()
{
// set vertex position
gl_Position = uModelViewProjectionMatrix * vec4(aPosition, 1.0);
// world space
vPosition = (uModelMatrix * vec4(aPosition, 1.0)).xyz;
vNormal = (uModelMatrix * vec4(aNormal, 0.0)).xyz;
vTangent = (uModelMatrix * vec4(aTangent, 0.0)).xyz;
vTexCoord = aTexCoord;
}
Fragment shader for wall:
#version 330 core
// interpolated values from the vertex shaders
in vec3 vPosition;
in vec3 vNormal;
in vec3 vTangent;
in vec2 vTexCoord;
// uniform input data
struct LightProperties
{
vec4 position;
vec4 ambient;
vec4 diffuse;
vec4 specular;
float shininess;
};
struct MaterialProperties
{
vec4 ambient;
vec4 diffuse;
vec4 specular;
};
uniform LightProperties uLightingProperties;
uniform MaterialProperties uMaterialProperties;
uniform vec3 uViewPoint;
uniform sampler2D uTextureSampler;
uniform sampler2D uNormalSampler;
// output data
out vec3 fColor;
void main()
{
// calculate normal map vectors
vec3 normal = normalize(vNormal);
vec3 tangent = normalize(vTangent);
vec3 biTangent = normalize(cross(tangent, normal));
vec3 normalMap = 2.0f * texture(uNormalSampler, vTexCoord).xyz - 1.0f;
// calculate vectors for lighting
vec3 N = normalize(mat3(tangent, biTangent, normal) * normalMap);
vec3 L;
// determine whether the light is a point light source or directional light
if(uLightingProperties.position.w == 0.0f)
L = normalize((uLightingProperties.position).xyz);
else
L = normalize((uLightingProperties.position).xyz - vPosition);
vec3 V = normalize(uViewPoint - vPosition);
vec3 R = reflect(-L, N);
// calculate Phong lighting
vec4 ambient = uLightingProperties.ambient * uMaterialProperties.ambient;
vec4 diffuse = uLightingProperties.diffuse * uMaterialProperties.diffuse * max(dot(L, N), 0.0);
vec4 specular = vec4(0.0f, 0.0f, 0.0f, 1.0f);
if(dot(L, N) > 0.0f)
{
specular = uLightingProperties.specular * uMaterialProperties.specular
* pow(max(dot(V, R), 0.0), uLightingProperties.shininess);
}
// set output color
fColor = (diffuse + specular + ambient).rgb;
fColor *= texture(uTextureSampler, vTexCoord).rgb;
}
PS: Sorry if I was a bit too irresponsible with my questions yesterday. Some of the advice I just didn't understand and thus didn't reply.
When you are drawing the 2nd part (wall), then you are binding the textures to the texture units GL_TEXTURE1 and GL_TEXTURE2:
glActiveTexture(GL_TEXTURE1);
glBindTexture(GL_TEXTURE_2D, g_textureID[6]);
glActiveTexture(GL_TEXTURE2);
glBindTexture(GL_TEXTURE_2D, g_textureID[7]);
But you are setting the texture unit indices 0 and 1 to the texture sampler uniforms uTextureSampler and uNormalSampler:
glUniform1i(g_texSamplerIndex, 0);
glUniform1i(g_normalSamplerIndex, 1);`
Adapt your code like this:
glUniform1i(g_texSamplerIndex, 1); // GL_TEXTURE1
glUniform1i(g_normalSamplerIndex, 2); // GL_TEXTURE2
Further the attribute index of "aTexCoord" is stored to texCoordIndex[i] for g_shaderProgramID[i]:
for (int i = 0; i < 2; i++)
{
....
texCoordIndex[i] = glGetAttribLocation(g_shaderProgramID[i], "aTexCoord");
.....
}
You have to be aware of this when set up the vertex attribute pointer and enable the vertex attribute
Change this:
glVertexAttribPointer(texCoordIndex[0], 2, GL_FLOAT, GL_FALSE, sizeof(Vertex2), reinterpret_cast<void*>(offsetof(Vertex2, texCoord)));
.....
glEnableVertexAttribArray(texCoordIndex[0]);
To this:
glVertexAttribPointer(texCoordIndex[1], 2, GL_FLOAT, GL_FALSE, sizeof(Vertex2), reinterpret_cast<void*>(offsetof(Vertex2, texCoord)));
.....
glEnableVertexAttribArray(texCoordIndex[1]);
And the error is "Access violation reading location in nvoglv64.dll"
The program worked as intended on my old AMD Radeon HD 6970. A few days ago I bought a GTX 970. Great card, but I would like my program to work. I want to render a quad to the screen for deferred rendering. I try to use OpenGL 4.4
Source:
Preparing the quad:
modelMatrix = mat4(1.0);
vertices.push_back(vec3(-1.0f, -1.0f, 0.0f));
vertices.push_back(vec3(1.0f, -1.0f, 0.0f));
vertices.push_back(vec3(1.0f, 1.0f, 0.0f));
vertices.push_back(vec3(-1.0f, -1.0f, 0.0f));
vertices.push_back(vec3(1.0f, 1.0f, 0.0f));
vertices.push_back(vec3(-1.0f, 1.0f, 0.0f));
normals.push_back(vec3(0.0f, 0.0f, 1.0f));
normals.push_back(vec3(0.0f, 0.0f, 1.0f));
normals.push_back(vec3(0.0f, 0.0f, 1.0f));
normals.push_back(vec3(0.0f, 0.0f, 1.0f));
normals.push_back(vec3(0.0f, 0.0f, 1.0f));
normals.push_back(vec3(0.0f, 0.0f, 1.0f));
indices.push_back(0);
indices.push_back(1);
indices.push_back(2);
indices.push_back(0);
indices.push_back(2);
indices.push_back(3);
uvs.push_back(vec2(0.0f, 0.0f));
uvs.push_back(vec2(1.0f, 0.0f));
uvs.push_back(vec2(1.0f, 1.0f));
uvs.push_back(vec2(0.0f, 0.0f));
uvs.push_back(vec2(1.0f, 1.0f));
uvs.push_back(vec2(0.0f, 1.0f));
indexCount = static_cast<int>(indices.size());
is2D = true;
unsigned int handle[2];
glGenBuffers(2, handle);
glBindBuffer(GL_ARRAY_BUFFER, handle[0]);
glBufferData(GL_ARRAY_BUFFER, vertices.size() * sizeof(glm::vec3), &vertices[0], GL_STATIC_DRAW);
glBindBuffer(GL_ARRAY_BUFFER, handle[1]);
glBufferData(GL_ARRAY_BUFFER, uvs.size() * sizeof(glm::vec3), &uvs[0], GL_STATIC_DRAW);
glGenVertexArrays(1, &array2D);
glBindVertexArray(array2D);
glBindBuffer(GL_ARRAY_BUFFER, handle[0]);
glVertexAttribPointer((GLuint)0, 3, GL_FLOAT, GL_FALSE, 0, ((GLubyte *)NULL + (0)));
glEnableVertexAttribArray(0); // Vertex position
glBindBuffer(GL_ARRAY_BUFFER, handle[1]);
glVertexAttribPointer((GLuint)2, 2, GL_FLOAT, GL_FALSE, 0, ((GLubyte *)NULL + (0)));
glEnableVertexAttribArray(1); // Texture coordinates
glBindVertexArray(0);
Rendering the quad:
// The following three lines are called in the render loop (as 2nd pass).
// I skip rendering meshes in the first pass to better understand this error.
//sp->useSubRoutine(srp2); // SP is the shader program
//sp->resetMatrices(); // Set matrices to mat4(1.0);
//dq->render(); // DQ is the display quad
glBindFramebuffer(GL_FRAMEBUFFER, fbo); // fbo is 0 for quad
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glDisable(GL_DEPTH_TEST);
if (shader != nullptr)
{
shader->use();
shader->setModelMatrix(modelMatrix);
}
if (is2D)
{
glBindVertexArray(array2D);
glDrawArrays(GL_TRIANGLES, 0, indexCount); // ERROR HERE
return;
}
Vertex Shader:
#version 440
layout(location = 0) in vec3 vertexPosition;
layout(location = 1) in vec2 vertexUV;
layout(location = 2) in vec3 vertexNormal;
centroid out vec2 UV;
out vec4 position;
out vec3 normal;
uniform mat4 uniMatModel;
uniform mat4 uniMatView;
uniform mat4 uniMatProjection;
uniform mat4 uniMatModelView;
uniform mat4 uniMatModelViewProjection;
uniform mat3 uniMatNormal;
void main()
{
UV = vertexUV;
position = uniMatModelView * vec4(vertexPosition, 1.0);
normal = normalize(uniMatNormal * vertexNormal);
gl_Position = uniMatModelViewProjection * vec4(vertexPosition, 1.0);
}
Fragment Shader:
#version 440
struct lightInfo {
vec4 position;
vec3 intensity;
bool isActive;
};
// IN
centroid in vec2 UV;
in vec4 position;
in vec3 normal;
// OUT
layout (location = 0) out vec4 fragColor;
layout (location = 1) out vec3 positionData;
layout (location = 2) out vec3 normalData;
layout (location = 3) out vec3 colorData;
// SUBROUTINES
subroutine void renderPassType();
subroutine uniform renderPassType renderPass;
// UNIFORMS
uniform sampler2D uniSamTexture;
uniform sampler2D uniSamAlpha;
uniform sampler2D uniSamAmbient;
uniform sampler2D uniSamSpecular;
uniform sampler2D uniSamShininess;
uniform lightInfo uniPointLights[32];
uniform vec3 uniVec3AmbientEmissiveness;
layout(binding=0) uniform sampler2D positionTex;
layout(binding=1) uniform sampler2D normalTex;
layout(binding=2) uniform sampler2D colorTex;
subroutine (renderPassType)
void renderWorld()
{
if (texture2D(uniSamAlpha, UV).rgb[0] == 1.0) // Alphamaps have to be inverted
{
discard;
}
else
{
colorData = texture2D(uniSamTexture, UV).rgb;
}
positionData = vec3(position.x, position.y, position.z);
normalData = normal;
fragColor = vec4(colorData, 1.0);
}
subroutine (renderPassType)
void renderLight()
{
fragColor = vec4(1.0,0.0,0.0,1.0); // For testing purposes set to red
}
void main()
{
renderPass();
}
Such problems can occure on NVIDIA cards when you try to read from a vertex buffer that does not have enough elements in it. For example rendering 9 vertices from a buffer that only contains 6. AMD interestingly does not complain about that.
In your case you bind a vertex buffer to attribute location 2, but you activate location 1. This:
glVertexAttribPointer((GLuint)2, 2, GL_FLOAT, GL_FALSE, 0, ((GLubyte *)NULL + (0)));
glEnableVertexAttribArray(1); // Texture coordinates
should actually be
||
\/
glVertexAttribPointer((GLuint)1, 2, GL_FLOAT, GL_FALSE, 0, ((GLubyte *)NULL + (0)));
glEnableVertexAttribArray(1); // Texture coordinates
Edit:
I just saw another thing
glBufferData(GL_ARRAY_BUFFER, uvs.size() * sizeof(glm::vec3), &uvs[0], GL_STATIC_DRAW);
uvs.size() equals 6 in your application, so OpenGL will try to read 6 * 3 = 18 float. Your uvs-array only contains 12 floats (since you are using vec2 here).
I seem to have broken the shaders in my program, here is their code:
vertex shader
#version 330 core
uniform mat4 camera;
uniform mat4 model;
layout(location = 0) in vec3 vert;
layout(location = 1) in vec3 vertNormal;
out vec3 fragVert;
out vec3 fragNormal;
void main() {
// Pass some variables to the fragment shader
fragNormal = vertNormal;
fragVert = vert;
// Apply all matrix transformations to vert
gl_Position = camera * model * vec4(vert, 1);
}
fragment shader
#version 150 core
uniform mat4 model;
uniform vec3 cameraPosition;
// material settings
uniform float materialShininess;
uniform vec3 materialSpecularColor;
uniform vec3 materialColor;
uniform struct Light {
vec3 position;
vec3 intensities; //a.k.a the color of the light
float attenuation;
float ambientCoefficient;
} light;
in vec3 fragNormal;
in vec3 fragVert;
out vec4 finalColor;
void main() {
vec3 normal = normalize(transpose(inverse(mat3(model))) * fragNormal);
vec3 surfacePos = vec3(model * vec4(fragVert, 1));
vec4 surfaceColor = vec4(materialColor, 1);
vec3 surfaceToLight = normalize(light.position - surfacePos);
vec3 surfaceToCamera = normalize(cameraPosition - surfacePos);
//ambient
vec3 ambient = light.ambientCoefficient * surfaceColor.rgb * light.intensities;
//diffuse
float diffuseCoefficient = max(0.0, dot(normal, surfaceToLight));
vec3 diffuse = diffuseCoefficient * surfaceColor.rgb * light.intensities;
//specular
float specularCoefficient = 0.0;
if(diffuseCoefficient > 0.0)
specularCoefficient = pow(max(0.0, dot(surfaceToCamera, reflect(-surfaceToLight, normal))), materialShininess);
vec3 specular = specularCoefficient * materialSpecularColor * light.intensities;
//attenuation
float distanceToLight = length(light.position - surfacePos);
float attenuation = 1.0 / (1.0 + light.attenuation * pow(distanceToLight, 2));
//linear color (color before gamma correction)
vec3 linearColor = ambient + attenuation*(diffuse + specular);
//final color (after gamma correction)
vec3 gamma = vec3(1.0/2.2);
finalColor = vec4(pow(linearColor, gamma), surfaceColor.a);
}
I have an asset that I am loading from an obj file, then drawing it like such:
void OpenGLView::run()
{
initializeAndSetupWindow(WINDOW_WIDTH, WINDOW_HEIGHT, "PhongBunny");
glClearColor(1.0f, 1.0f, 0.0f, 1.0f);
loadBunnyAsset();
AssetInstance bunny1;
bunny1.asset = bunny;
bunny1.position = glm::vec3(2.0f, 2.0f, 2.0f);
bunny1.scale = glm::vec3(1.0f, 1.0f, 1.0f);
do{
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
loadUniforms(bunny1);
glEnableVertexAttribArray(0);
glBindBuffer(GL_ARRAY_BUFFER, bunny.vertexBuffer);
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, nullptr);
glEnableVertexAttribArray(1);
glBindBuffer(GL_ARRAY_BUFFER, bunny.normalBuffer);
glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 0, nullptr);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, bunny.elementBuffer);
glDrawElements(GL_TRIANGLES, bunny.elementsSize, GL_UNSIGNED_INT, (void*)0);
glDisableVertexAttribArray(0);
glDisableVertexAttribArray(1);
glfwSwapBuffers(window);
glfwPollEvents();
} while (!glfwWindowShouldClose(window));
glfwDestroyWindow(window);
glfwTerminate();
}
with this being the function to load uniforms:
void OpenGLView::loadUniforms(AssetInstance assetInstance)
{
Asset* asset = &assetInstance.asset;
glUseProgram(asset->shaderProgramID);
glm::mat4 Projection = glm::perspective(45.0f, 4.0f / 3.0f, 0.1f, 1000.0f);
glm::mat4 camera = Projection * getViewMatrix();
glm::mat4 model = translate(assetInstance.position) * scale(assetInstance.position);
GLuint cameraID = glGetUniformLocation(asset->shaderProgramID, "camera");
GLuint modelID = glGetUniformLocation(asset->shaderProgramID, "model");
GLuint cameraPositionID = glGetUniformLocation(asset->shaderProgramID, "cameraPosition");
GLuint lightPositionID = glGetUniformLocation(asset->shaderProgramID, "light.position");
GLuint lightIntensitiesID = glGetUniformLocation(asset->shaderProgramID, "light.intensities");
GLuint lightAttenuationID = glGetUniformLocation(asset->shaderProgramID, "light.attenuation");
GLuint lightAmbientCoefficientID = glGetUniformLocation(asset->shaderProgramID, "light.ambientCoefficient");
GLuint materialColorID = glGetUniformLocation(asset->shaderProgramID, "materialColor");
GLuint materialShininessID = glGetUniformLocation(asset->shaderProgramID, "materialShininess");
GLuint materialSpecularColorID = glGetUniformLocation(asset->shaderProgramID, "materialSpecularColor");
glUniformMatrix4fv(cameraID, 1, GL_FALSE, &camera[0][0]);
glUniformMatrix4fv(modelID, 1, GL_FALSE, &model[0][0]);
glUniform3fv(cameraPositionID, 1, &cameraPosition[0]);
glUniform3fv(lightPositionID, 1, &light.position[0]);
glUniform3fv(lightIntensitiesID, 1, &light.intensities[0]);
glUniform1f(lightAttenuationID, light.attenuation);
glUniform1f(lightAmbientCoefficientID, light.ambientCoefficient);
glUniform3fv(materialColorID, 1, &assetInstance.materialColor[0]);
glUniform1f(materialShininessID, assetInstance.materialShininess);
glUniform3fv(materialSpecularColorID, 1, &assetInstance.materialSpecularColor[0]);
}
and some setup being done here:
OpenGLView::OpenGLView()
{
light.position = glm::vec3(0.0f, 7.0f, 3.0f);
light.intensities = glm::vec3(0.3f, 0.3, 0.3f);
light.attenuation = 0.3f;
light.ambientCoefficient = 0.005f;
cameraPosition = glm::vec3(5.0f, 3.0f, 8.0f);
}
For a while I had the bunny1's position set to 0, 0, 0 which caused it to not be drawn at all, I can't figure out why that is? Then when I changed it to 1, 1, 1 it started to draw, but now my key_callback function (which rotates and scales the bunny) stopped working. Also, here are my translate and scale functions:
glm::mat4 OpenGLView::translate(glm::vec3 position)
{
return glm::translate(glm::mat4(), position);
}
glm::mat4 OpenGLView::scale(glm::vec3 size)
{
return glm::scale(glm::mat4(), size);
}
and I can't figure out why changing bunny1.position seems to scale the bunny instead of translating its position?
The reason why your bunny's scale changes when changing bunny1.position is because you scale your bunny by bunny1.position:
glm::mat4 model = translate(assetInstance.position) * scale(assetInstance.position);
That might also be the reason why the bunny disapears when setting it's position to (0,0,0) since you then scale it to 0.