My Problem is similar to the problems mentioned here.
My Github commit:
When i try to draw a cube in opengl 3.3 on windows with c++, glfw and glad i have the problem, that it only displays a solid color(colour?) based on the original texture. It seems to be a problem with the texture cordinates which are not applied. Shader and cpp code and also RenderDoc further down the post. Ask for more if u need.
Vertex Shader:
#version 330 core
layout (location = 0) in vec3 aPos;
layout (location = 1) in vec2 aTexCoord;
layout (location = 2) in vec3 aNormal;
out vec3 FragPos;
out vec2 TexCoord;
out vec3 Normal;
uniform mat4 model;
uniform mat4 view;
uniform mat4 projection;
void main(){
gl_Position = projection * view * model * vec4(aPos, 1.0f);
FragPos = vec3(model * vec4(aPos, 1.0));
TexCoord = aTexCoord;
Normal = aNormal;
};
Fragment Shader
#version 330 core
in vec3 FragPos;
in vec2 TexCoord;
in vec3 Normal;
struct DirLight {
vec3 direction;
vec3 ambient;
vec3 diffuse;
vec3 specular;
};
uniform DirLight dirLight;
vec3 CalcDirLight(DirLight light, vec3 normal, vec3 viewDir);
struct PointLight {
vec3 position;
float constant;
float linear;
float quadratic;
vec3 ambient;
vec3 diffuse;
vec3 specular;
};
#define NR_POINT_LIGHTS 1
uniform PointLight pointLights[NR_POINT_LIGHTS];
vec3 CalcPointLight(PointLight light, vec3 normal, vec3 fragPos, vec3 viewDir);
struct Material {
vec3 specular;
float shininess;
};
uniform Material material;
uniform sampler2D tex_sampler;
uniform vec3 viewPos;
out vec4 FragColor;
void main()
{
// properties
vec3 norm = normalize(Normal);
vec3 viewDir = normalize(viewPos - FragPos);
// phase 1: Directional lighting
vec3 result = CalcDirLight(dirLight, norm, viewDir);
// phase 2: Point lights
for(int i = 0; i < NR_POINT_LIGHTS; i++)
result += CalcPointLight(pointLights[i], norm, FragPos, viewDir);
FragColor = texture(tex_sampler, TexCoord);// * vec4(result, 1.0);
}
vec3 CalcDirLight(DirLight light, vec3 normal, vec3 viewDir)
{
vec3 lightDir = normalize(-light.direction);
// diffuse shading
float diff = max(dot(normal, lightDir), 0.0);
// specular shading
vec3 reflectDir = reflect(-lightDir, normal);
float spec = pow(max(dot(viewDir, reflectDir), 0.0), material.shininess);
// combine results
vec3 ambient = light.ambient * vec3(texture(tex_sampler, TexCoord));
vec3 diffuse = light.diffuse * diff * vec3(texture(tex_sampler, TexCoord));
vec3 specular = light.specular * spec * vec3(1.0f, 0.0f, 0.0f);
//return (ambient + diffuse + specular);
return (ambient + diffuse);
}
vec3 CalcPointLight(PointLight light, vec3 normal, vec3 fragPos, vec3 viewDir)
{
vec3 lightDir = normalize(light.position - fragPos);
// diffuse shading
float diff = max(dot(normal, lightDir), 0.0);
// specular shading
vec3 reflectDir = reflect(-lightDir, normal);
float spec = pow(max(dot(viewDir, reflectDir), 0.0), material.shininess);
// attenuation
float distance = length(light.position - fragPos);
float attenuation = 1.0 / (light.constant + light.linear * distance +
light.quadratic * (distance * distance));
// combine results
vec3 ambient = light.ambient * vec3(texture(tex_sampler, TexCoord));
vec3 diffuse = light.diffuse * diff * vec3(texture(tex_sampler, TexCoord));
vec3 specular = light.specular * spec * vec3(1.0f, 1.0f, 1.0f);
ambient *= attenuation;
diffuse *= attenuation;
specular *= attenuation;
return (ambient + diffuse + specular);
}
I load my texture and draw the cube:
glEnable(GL_TEXTURE_2D);
glActiveTexture(GL_TEXTURE0);
unsigned int texture = makeTexture(textureDir + "diamond_ore.png");
[...]
defaultShader.use();
// CAMERA
// model matrix set further down, dynamically for each object
//view matrix, transform world space to camera space
glm::mat4 view = glm::lookAt(cameraPos, cameraPos + cameraFront, cameraUp);
defaultShader.setMatrix4fv("view", view);
//projection matrix, view space to device cordinates
glm::mat4 projection = glm::perspective(glm::radians(fov), 800.0f / 600.0f, 0.1f, 100.0f);
defaultShader.setMatrix4fv("projection", projection);
// DRAWING
//clear color and depth buffer
glClearColor(0.2f, 0.3f, 0.3f, 1.0f);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
////vertex data, shaders
defaultShader.setVec3("viewPos", cameraPos.x, cameraPos.y, cameraPos.z);
defaultShader.setInt("tex_sampler", 0);
defaultShader.setVec3("material.specular", 1.0f, 0.0f, 0.0f);
defaultShader.setFloat("material.shininess", 32.0f);
defaultShader.setVec3("dirLight.direction", 0.0f, -1.0f, 0.0f);
defaultShader.setVec3("dirLight.ambient", 1.0f, 1.0f, 1.0f);
defaultShader.setVec3("dirLight.diffuse", 0.8f, 0.8f, 0.8f); // darken diffuse light a bit
defaultShader.setVec3("dirLight.specular", 1.0f, 1.0f, 1.0f);
defaultShader.setVec3("pointLights[0].position", -1.0f, -1.0f, -1.0f);
defaultShader.setVec3("pointLights[0].ambient", 0.2f, 0.2f, 0.2f);
defaultShader.setVec3("pointLights[0].diffuse", 0.8f, 0.8f, 0.8f); // darken diffuse light a bit
defaultShader.setVec3("pointLights[0].specular", 1.0f, 1.0f, 1.0f);
defaultShader.setFloat("pointLights[0].constant", 1.0f);
defaultShader.setFloat("pointLights[0].linear", 0.045f);
defaultShader.setFloat("pointLights[0].quadratic", 0.0075f);
model = glm::mat4(1.0f);
model = glm::translate(model, glm::vec3(-1.0, -1.0, -1.0));
defaultShader.setMatrix4fv("model", model);
glEnable(GL_TEXTURE_2D);
glActiveTexture(GL_TEXTURE0);
glDrawArrays(GL_TRIANGLES, 0, 36);
float cube_vertices[] = {
-0.5f, -0.5f, -0.5f, 0.0f, 0.0f, 0.0f, 0.0f, -1.0f,
0.5f, -0.5f, -0.5f, 1.0f, 0.0f, 0.0f, 0.0f, -1.0f,
0.5f, 0.5f, -0.5f, 1.0f, 1.0f, 0.0f, 0.0f, -1.0f,
0.5f, 0.5f, -0.5f, 1.0f, 1.0f, 0.0f, 0.0f, -1.0f,
-0.5f, 0.5f, -0.5f, 0.0f, 1.0f, 0.0f, 0.0f, -1.0f,
-0.5f, -0.5f, -0.5f, 0.0f, 0.0f, 0.0f, 0.0f, -1.0f,
-0.5f, -0.5f, 0.5f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f,
0.5f, -0.5f, 0.5f, 1.0f, 0.0f, 0.0f, 0.0f, 1.0f,
0.5f, 0.5f, 0.5f, 1.0f, 1.0f, 0.0f, 0.0f, 1.0f,
0.5f, 0.5f, 0.5f, 1.0f, 1.0f, 0.0f, 0.0f, 1.0f,
-0.5f, 0.5f, 0.5f, 0.0f, 1.0f, 0.0f, 0.0f, 1.0f,
-0.5f, -0.5f, 0.5f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f,
-0.5f, 0.5f, 0.5f, 1.0f, 0.0f, -1.0f, 0.0f, 0.0f,
-0.5f, 0.5f, -0.5f, 1.0f, 1.0f, -1.0f, 0.0f, 0.0f,
-0.5f, -0.5f, -0.5f, 0.0f, 1.0f, -1.0f, 0.0f, 0.0f,
-0.5f, -0.5f, -0.5f, 0.0f, 1.0f, -1.0f, 0.0f, 0.0f,
-0.5f, -0.5f, 0.5f, 0.0f, 0.0f, -1.0f, 0.0f, 0.0f,
-0.5f, 0.5f, 0.5f, 1.0f, 0.0f, -1.0f, 0.0f, 0.0f,
0.5f, 0.5f, 0.5f, 1.0f, 0.0f, 1.0f, 0.0f, 0.0f,
0.5f, 0.5f, -0.5f, 1.0f, 1.0f, 1.0f, 0.0f, 0.0f,
0.5f, -0.5f, -0.5f, 0.0f, 1.0f, 1.0f, 0.0f, 0.0f,
0.5f, -0.5f, -0.5f, 0.0f, 1.0f, 1.0f, 0.0f, 0.0f,
0.5f, -0.5f, 0.5f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f,
0.5f, 0.5f, 0.5f, 1.0f, 0.0f, 1.0f, 0.0f, 0.0f,
-0.5f, -0.5f, -0.5f, 0.0f, 1.0f, 0.0f, -1.0f, 0.0f,
0.5f, -0.5f, -0.5f, 1.0f, 1.0f, 0.0f, -1.0f, 0.0f,
0.5f, -0.5f, 0.5f, 1.0f, 0.0f, 0.0f, -1.0f, 0.0f,
0.5f, -0.5f, 0.5f, 1.0f, 0.0f, 0.0f, -1.0f, 0.0f,
-0.5f, -0.5f, 0.5f, 0.0f, 0.0f, 0.0f, -1.0f, 0.0f,
-0.5f, -0.5f, -0.5f, 0.0f, 1.0f, 0.0f, -1.0f, 0.0f,
-0.5f, 0.5f, -0.5f, 0.0f, 1.0f, 0.0f, 1.0f, 0.0f,
0.5f, 0.5f, -0.5f, 1.0f, 1.0f, 0.0f, 1.0f, 0.0f,
0.5f, 0.5f, 0.5f, 1.0f, 0.0f, 0.0f, 1.0f, 0.0f,
0.5f, 0.5f, 0.5f, 1.0f, 0.0f, 0.0f, 1.0f, 0.0f,
-0.5f, 0.5f, 0.5f, 0.0f, 0.0f, 0.0f, 1.0f, 0.0f,
-0.5f, 0.5f, -0.5f, 0.0f, 1.0f, 0.0f, 1.0f, 0.0f,
};
buffers.cpp:
//VAO
VAO::VAO() {
glGenVertexArrays(1, &this->vaoID);
}
void VAO::bind(){
glBindVertexArray(this->vaoID);
}
void VAO::fillFirst() {
this->bind();
this->vbos[0].fillBuffer();
this->setAttribPointer(0, 3, GL_FLOAT, false, 8, 0);
this->setAttribPointer(1, 2, GL_FLOAT, false, 8, 3);
this->setAttribPointer(2, 3, GL_FLOAT, false, 8, 5);
if (this->ebos.size() > 0) {
this->ebos[0].fillBuffer();
}
}
void VAO::setAttribPointer(int attribID, int length, int type, bool normalized, int stride, int offset) {
this->bind();
glVertexAttribPointer(
attribID,
length,
type,
normalized,
stride * sizeof(float),
(void*)(offset * sizeof(float))
);
glEnableVertexAttribArray(attribID);
}
//VBO
VBO::VBO(std::vector<Vertex> vertices) {
glGenBuffers(1, &this->vboID);
this->vertices = vertices;
}
void VBO::fillBuffer() {
glBindBuffer(GL_ARRAY_BUFFER, this->vboID);
std::cout << sizeof(this->vertices[0]) << ":" << sizeof(&this->vertices[0]) << std::endl;
glBufferData(GL_ARRAY_BUFFER, this->vertices.size() * sizeof(this->vertices[0]), &this->vertices[0], GL_STATIC_DRAW);
}
RenderDoc:
Edit 1:
I replaced FragColor = texture(tex_sampler, TexCoord);// * vec4(result, 1.0);
in the fragment shader with FragColor = vec4(TexCoord.x * TexCoord.x, TexCoord.y * TexCoord.y, 1.0, 1.0);
which leads to a regular change in color and implies, that the texture cordinates are passed to the fragment shader. There seem to be wrong or missing parts somewhere which are required for using opengl textures.
You can clearly see in renderdoc that the texcoords your shader is receiving are flat-out wrong. If you look closely, you can even see that your aTexCoord
vector is the x
and y
component of your normals.
The code pasted in this question makes it appear as if your vertex format is posX, posY, posZ, texU, texV, nrmX, nrmY, nrmZ
, and this is exactly what you set up with glVertexAttribPointer
. But you left out an important part of your code: what data you actually write into your buffer, and what you have there is:
std::vector<Vertex> cubevert; for (int i = 0; i < sizeof(cube_vertices) / szeof(float); i += 8) { Vertex vert; vert.Position = glm::vec3(cube_vertices[i], cube_vertices[i + 1], cube_vertices[i + 2]); vert.TexCoords = glm::vec2(cube_vertices[i +> 3], cube_vertices[i + 4]); vert.Normal = glm::vec3(cube_vertices[i +> 5], cube_vertices[i + 6], cube_vertices[i + 7]); cubevert.push_back(vert); }
So you actually-re-organize this data to a different format defined as:
struct Vertex { glm::vec3 Position; glm::vec3 Normal; glm::vec2 TexCoords; };
Which simply means you use the first two components of the normal as your texcoords, and the third component of the normal together with the texcoords as normal.