Texture Projection in GLSL - glsl

I'm trying to implement texture projection based directly on this example at oZone3d. My environment is OpenGL ES 2.0 on Android 2.2.
Matrix math has never been my strong point and I suspect that my problem lies somewhere in the texture projection matrix setup (texGenMatrix). I have tried everything imaginable to get this working but the projection doesn't come out correctly. I'd greatly appreciate some extra eyes on my code. Thanks.
Not shown here is my geometry (a horizontal plane through the origin), and some other plumbing like shader uniform/attribute binds.
Camera Setup :
// Set the camera projection matrix
Matrix.frustumM(cameraProjMatrix, 0,
-nearPlaneSize.x, nearPlaneSize.x, // near plane left/right
-nearPlaneSize.y, nearPlaneSize.y, // near plane bottom/top
nearPlaneDistance, farPlaneDistance // near/far plane distance
);
// Set the camera view matrix
Matrix.setLookAtM(cameraViewMatrix, 0,
0, 100, 100, // eye
0, 0, 0, // center
0, 1, 0 // up-vector
);
// Translate the model as needed
Matrix.translateM(modelMatrix, 0, x, y, z);
// Calculate the model * view matrix
Matrix.multiplyMM(modelViewMatrix, 0, cameraViewMatrix, 0, modelMatrix, 0);
// Calculate the inverse camera view matrix (needed in the vert shader)
Matrix.invertM(inverseCameraViewMatrix, 0, cameraViewMatrix, 0);
Texture Projection setup :
// Set a texture projection matrix
Matrix.frustumM(texProjMatrix, 0,
-nearPlaneSize.x, nearPlaneSize.x, // near plane left/right
-nearPlaneSize.y, nearPlaneSize.y, // near plane bottom/top
nearPlaneDistance, farPlaneDistance // near/far plane distance
);
// Set the texture projection to point down at the origin
Matrix.setLookAtM(texViewMatrix, 0,
0, 100, 10, // eye
0, 0, 0, // center
0, 1, 0 // up-vector
);
// scale bias
float[] scaleBiasMatrix = new float[] { 0.5f, 0.0f, 0.0f, 0.0f,
0.0f, 0.5f, 0.0f, 0.0f,
0.0f, 0.0f, 0.5f, 0.0f,
0.5f, 0.5f, 0.5f, 1.0f
};
// calculate the TexGenMatrix
Matrix.multiplyMM(texGenMatrix, 0, scaleBiasMatrix, 0, texProjMatrix, 0);
Matrix.multiplyMM(texGenMatrix, 0, texGenMatrix, 0, texViewMatrix, 0);
The vertex shader :
attribute vec3 aPosition; // vertex x y z
uniform mat4 texGenMatrix;
uniform mat4 modelViewMatrix;
uniform mat4 cameraProjMatrix;
varying vec4 vProjCoord;
void main() {
gl_Position = cameraProjMatrix * modelViewMatrix * aPosition;
vec4 posEye = modelViewMatrix * aPosition;
vec4 posWorld = inverseCameraViewMatrix * posEye;
vProjCoord = texGenMatrix * posWorld;
}
Fragment shader :
uniform sampler2D projectionMap;
varying vec4 vProjCoord;
void main() {
vec3 finalColor = vec3( 0.5, 0.5, 0.5);
if (vProjCoord.q > 0.0) {
vec4 ProjMapColor = texture2DProj(projectionMap, vProjCoord);
finalColor += ProjMapColor.rgb;
}
gl_FragColor = vec4(finalColor, 1.0);
}

Related

Move circle with Projection matrix

I need some help trying to move my circle with view matrix. I can position the circle but cant move it. How can i make this happen?
Right now the the bounding rectangle moves but not the circle.
I've tried to center the circle in the rectangle and but this doesnt work.
Any help is appreciated!
#include <glew.h>
#include "circle.h"
Circle::Circle()
{
const std::string vertexShaderSource = R"END(
#version 330 core
layout (location = 0) in vec4 vertex; // <vec2 position, vec2 texCoords>
uniform mat4 model;
uniform mat4 projection;
uniform mat4 view;
void main()
{
gl_Position = projection * view * model * vec4(vertex.xy, 0.0, 1.0);
}
)END";
const std::string fragmentShaderSource = R"END(
#version 330 core
out vec4 color;
uniform vec2 dim;
uniform vec2 pos;
/**
* Convert r, g, b to normalized vec3
*/
vec3 rgb(float r, float g, float b) {
return vec3(r / 255.0, g / 255.0, b / 255.0);
}
/**
* Draw a circle at vec2 `pos` with radius `rad` and
* color `color`.
*/
vec4 circle(vec2 uv, vec2 pos, float rad, vec3 color) {
float d = length(pos - uv) - rad;
float t = clamp(d, 0.0, 1.0);
return vec4(color, 1.0 - t);
}
void main() {
vec2 uv = gl_FragCoord.xy;
float radius = 60;
vec2 center = pos;
// Background layer
vec4 layer1 = vec4(rgb(210.0, 222.0, 228.0), 0.3);
// Circle
vec3 red = rgb(225.0, 95.0, 60.0);
vec4 layer2 = circle(uv, center, radius, red);
// Blend the two
color = mix(layer1, layer2, layer2.a);
}
)END";
shader.Compile(vertexShaderSource.c_str(), fragmentShaderSource.c_str());
// Configure VAO etc..
}
void Circle::Update(float deltaTime, int width, int height)
{
// Activate shader
shader.Activate();
auto camera = Services::Get<RenderService>()->camera;
glm::mat4 model = glm::mat4(1.0f);
glm::mat4 view;
if (skipPan == false)
{
view = camera.GetViewMatrix();
}
else
{
view = glm::mat4{1.0f};
}
projection = glm::ortho(0.0f, static_cast<float>(width),
static_cast<float>(height), 0.0f, -1.0f, 1.0f);
model = glm::translate(model, glm::vec3(transform.position.x, transform.position.y, 0.0f));
model = glm::scale(model, glm::vec3(transform.dimension.width, transform.dimension.height, 1.0f));
shader.setMat4("projection", projection);
shader.setMat4("model", model);
shader.setMat4("view", view);
shader.setVec2("dim", glm::vec2{transform.dimension.width, transform.dimension.height});
shader.setVec2("pos", glm::vec2{transform.position.x, transform.position.y});
shader.setVec4("spriteColor", glm::vec4{style.Background.r, style.Background.g, style.Background.b, style.Background.a});
glBindVertexArray(vao);
glDrawArrays(GL_TRIANGLES, 0, 6);
}
This is an issue i've been struggeling with for some time now. This applies to other shapes aswell that renders with SDF and such.
// configure VAO/VBO
const float vertices[] = {
0.0f, 1.0f, 0.0f,
1.0f, 0.0f, 1.0f,
0.0f, 0.0f, 0.0f,
0.0f, 1.0f, 0.0f,
1.0f, 1.0f, 1.0f,
1.0f, 0.0f, 1.0f};
glGenVertexArrays(1, &vao);
glGenBuffers(1, &vbo);
glBindBuffer(GL_ARRAY_BUFFER, vbo);
glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);
glBindVertexArray(vao);
glEnableVertexAttribArray(0);
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 3 * sizeof(float), (void *)0);
glBindBuffer(GL_ARRAY_BUFFER, 0);
glBindVertexArray(0);
You say that you're trying to move the circle with the view matrix. You indeed pass that matrix to your vertex shader and use it in the computation of gl_Position. However, your fragment shader calculation is based on gl_FragCoord and doesn't incorporate the view matrix in any way. Remember that gl_FragCoord is the fragment coordinates relative to the framebuffer bottom-left corner (usually), and is therefore not affected by the model/view/projection transformations.
To solve this, you can do any of the following:
Calculate the fragment coordinates of the center of your circle in Circle::Update and pass that to the pos uniform:
glm::vec4 pos = view*glm::vec4{transform.position.x, transform.position.y, 0.0f, 1.0f};
shader.setVec2("pos", pos.xy);
Apply the viewport transformation in the fragment shader -- same as above but done in the shader. This is kinda ugly as you would be applying view but not model because the later is already accounted for in the value of pos. Also it involves more calculations in the fragment shader.
Change your fragment shader to work off texture coordinates instead of gl_FragCoord. If you set fixed texture coordinates at the vertices of the quad, then the interpolated coordinates within the quad will transform correctly with regards to any of the view/model/projection, thus handling scaling or even perspective projections out-of-the-box. This would probably be the neatest solution in your case. (That being said, rasterization based on gl_FragCoord is sometimes necessary to avoid artifacts on the seam between the two triangles of the quad.)

Draw a 2D Quad in OpenGL

Whenever I think I understand something about openGL I find I don't understand anything.
I don't understand what I'm doing wrong.
The quad is not rendered.
Here is how I init the data
std::vector<glm::vec3> vertices;
vertices.resize(6);
// first triangle
vertices[0] = glm::vec3(x+w, y, 0.0f); // top right
vertices[1] = glm::vec3(x+w, y+h, 0.0f); // bottom right
vertices[2] = glm::vec3(x, y, 0.0f); // top left
// second triangle
vertices[3] = glm::vec3(x+w, y+h, 0.0f); // bottom right
vertices[4] = glm::vec3(x, y+h, 0.0f); // bottom left
vertices[5] = glm::vec3(x, y, 0.0f); // top left
Where (x, y) is coord of the top left corner in pixel screen position and (w, h) is the length of the sides of the quad
This is how I set in the GPU the data
glGenVertexArrays(1, &vao);
glBindVertexArray(vao);
glGenBuffers(1, &vbo);
glBindBuffer(GL_ARRAY_BUFFER, vbo);
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, nullptr);
glEnableVertexAttribArray(0);
glBufferData(GL_ARRAY_BUFFER, vertices.size() * sizeof(glm::vec3), vertices.data(), GL_STATIC_DRAW);
glBindVertexArray(0);
This is how I render it
glBindVertexArray(vao);
glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
glDrawArrays(GL_TRIANGLES, 0, 6);
glBindVertexArray(0);
And these are my vertex and fragment shader
#version 330 core
layout (location = 0) in vec3 position;
void main() {
gl_Position = vec4(position, 1.0);
}
#version 330 core
out vec4 outColor;
void main() {
outColor = vec4(1.0);
}
UPDATE
How Rabbit76 point out: I do not see the rectangle, because it is outside the view. If you don't use a projection matrix, the vertex coordinates must be in range [-1.0, 1.0]. If you want to use "window" coordinates you must use an orthographic projection"
So I changed the vertex shader in the following way and everything works!
#version 330 core
layout (location = 0) in vec3 position;
uniform vec2 viewport; //Width and Height of the viewport
void main() {
// From pixels to 0-1
vec2 coord = position.xy / viewport;
// Flip Y so that 0 is top
coord.y = (1.0-coord.y);
// Map to NDC -1,+1
coord.xy = coord.xy * 2.0 - 1.0;
gl_Position = vec4(coord.xy, 0.0, 1.0);
}
You don't see the rectangle because it's out of view. If you are not using a projection matrix, the vertex coordinates must be in the range [-1.0, 1.0]. If you want to use "window" coordinates you must use an Orthographic projection.
You need to transform the vertex coordinates through the projection matrix. This is usually done in the vertex shader. However, it is also possible to transform the vertex coordinates on the CPU. Use glm::ortho to define the orthographic projection matrix and transform the vertices:
glm::mat4 projection = glm::ortho(0.0f, window_width, window_height, 0.0f, -1.0f, 1.0f);
for (auto &vertex : vertices)
vertex = glm::vec3(projection * glm::vec4(vertex, 1.0f));

OPENGL How do I correctly render these 2 objects with different textures/mapping?

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]);

When I rotate model-view matrix should my light position preserve and only the model will rotate?

Here is my code snippet how I rotate the model-view matrix:
mat4 modelViewMatrix;
vec3 eyePosition = vec3(0, 0, 6);
vec3 centerPosition = vec3(0, 0, 0);
vec3 upVector = vec3(0, 1, 0);
modelViewMatrix = glm::lookAt(eyePosition, centerPosition, upVector);
vec3 axis = vec3(0, 1, 0);
modelViewMatrix = glm::rotate(modelViewMatrix, rotation, axis);
As much as I know model-view matrix is the transformation matrix that is responsible for going from model coordinate from to eye/camera coordinate frame.
So if I have two uniforms such as:
vec4 lightPosition = vec4(15.0f, 0.0f, 0.0f, 1.0f);
vec3 lightIntensity = vec3(1.0f, 0.0f, 0.0f);
that I use to calculate ADS Phong shading using GLSL my model should rotate but the light should stay at the same position, right?
Sorry the code is not compile-able, but I am asking about general concept and hope this gives you enough info to be able to advice me. Thanks!

How to position an object in model / view / world space?

I have a cube which is defined with the centre at 0,0,0 and the edges reaching out to -1/+1 (i.e. the cube has width, height, depth of 2).
I then setup the following matrices:
glm::mat4 modelMat4;
modelMat4 = glm::translate(modelMat4, 0.0f, 0.0f, 200.f);
modelMat4 = glm::scale(modelMat4, 200.0f, 200.0f, 200.0f);
glm::mat4 viewMat4;
viewMat4 = glm::lookAt(glm::vec3(0.0f, 0.0f, zNear),
glm::vec3(0.0f, 0.0f, zFar),
glm::vec3(0.0f, 1.0f, 0.0f));
// initialWidth = window width
// initialHeight = window height
// zNear = 1.0f
// zFar = 1000.0f
glm::mat4 projectionMat4;
projectionMat4 = glm::frustum(-initialWidth / 2.0f, initialWidth / 2.0f, -initialHeight / 2.0f, initialHeight / 2.0f, zNear, zFar);
But the middle of my object appears at the near z-plane (i.e. I can only see the back half of my cube, from the inside).
If I adjust the model transform to be:
glm::translate(modelMat4, 0.0f, 0.0f, 204.f);
Then I can see the front side of my cube as well.
If I change the model transform to be:
glm::translate(modelMat4, 0.0f, 0.0f, 250.f);
Then the cube only rasterises at approx 2x2x2 pixels.
What am I misunderstanding about model, view projection matrices? I was expecting the transform to be linear, but the z-plane disappears between 200 and 250. Even though the planes are defined between 1.0f and 1000.0f.
Edit: My shader code is below:
#version 100
layout(location = 0) in vec3 v_Position;
layout(location = 1) in vec4 v_Colour;
layout(location = 2) uniform mat4 v_ModelMatrix;
layout(location = 3) uniform mat4 v_ViewMatrix;
layout(location = 4) uniform mat4 v_ProjectionMatrix;
out vec4 f_inColour;
void main()
{
gl_Position = v_ProjectionMatrix * v_ViewMatrix * v_ModelMatrix * vec4(v_Position, 1.0);
f_inColour = v_Colour;
}
You didn't show how you are multiplying your matrices, but for what you describe, its seems that it could be doing wrong. Be sure to do in this order:
MVP = projectionMat4 * viewMat4 * modelMat4;
UPDATED
Looking more carefully into your code, it is seeming that you are lacking a multiplication to concanate your transformations:
modelMat4 = glm::translate(modelMat4, 0.0f, 0.0f, 200.f);
modelMat4 *= glm::scale(modelMat4, 200.0f, 200.0f, 200.0f); // <-- here
so, modelMat4 will be the results of a scale and then a translation