c++openglglslshadergeometry-shader

OpenGL geometry shader passing texture coordinates


I'm having issues with passing my texture coordinates correctly through a geometry shader. My texture coordinates getting all messed up when it ends up in my fragment shader. Here's the vertex shader:

#version 330 core

layout(location = 0) in vec3 position;
layout(location = 1) in vec3 normal;
layout(location = 2) in vec2 texCoord;

out VS_OUT
{
    vec3 v_Normal;
    vec2 v_TexCoord;
    vec3 v_FragPos;
} vs_out;

uniform mat4 u_Model;
uniform mat4 u_View;
uniform mat4 u_Projection;

void main()
{
    gl_Position = u_Projection * u_View * u_Model * vec4(position, 1.0);
    vs_out.v_Normal = normalize(mat3(transpose(inverse(u_Model))) * normal);
    vs_out.v_TexCoord = texCoord;
    vs_out.v_FragPos = vec3(u_Model * vec4(position, 1.0));
}

Geometry shader:

#version 330 core

layout(triangles) in;
layout(triangle_strip, max_vertices = 3) out;

in VS_OUT
{
    vec3 v_Normal;
    vec2 v_TexCoord;
    vec3 v_FragPos;
} gs_in[];

out GS_OUT
{
    vec3 v_Normal;
    vec2 v_TexCoord;
    vec3 v_FragPos;
} gs_out;

uniform float u_Time;

vec4 explode(vec4 position, vec3 normal)
{
    float magnitude = 2.0;
    vec3 direction = normal * ((sin(u_Time) + 1.0) / 2.0) * magnitude;
    return position + vec4(direction, 0.0);
}

vec3 GetNormal()
{
    vec3 a = vec3(gl_in[0].gl_Position) - vec3(gl_in[1].gl_Position);
    vec3 b = vec3(gl_in[2].gl_Position) - vec3(gl_in[1].gl_Position);
    return normalize(cross(a, b));
}

void main()
{
    vec3 normal = GetNormal();

    gl_Position = explode(gl_in[0].gl_Position, normal);
    gs_out.v_Normal = gs_in[0].v_Normal;
    gs_out.v_TexCoord = gs_in[0].v_TexCoord;
    gs_out.v_FragPos = vec3(explode(vec4(gs_in[0].v_FragPos, 1.0), normal));
    EmitVertex();

    gl_Position = explode(gl_in[1].gl_Position, normal);
    gs_out.v_Normal = gs_in[1].v_Normal;
    gs_out.v_TexCoord = gs_in[1].v_TexCoord;
    gs_out.v_FragPos = vec3(explode(vec4(gs_in[1].v_FragPos, 1.0), normal));
    EmitVertex();

    gl_Position = explode(gl_in[2].gl_Position, normal);
    gs_out.v_Normal = gs_in[1].v_Normal;
    gs_out.v_TexCoord = gs_in[1].v_TexCoord;
    gs_out.v_FragPos = vec3(explode(vec4(gs_in[1].v_FragPos, 1.0), normal));
    EmitVertex();

    EndPrimitive();
}

Fragment shader:

#version 330 core

struct Material
{
    sampler2D ambient;
    sampler2D diffuse;
    sampler2D specular;
    sampler2D emissive;
    float shininess;
};

struct DirectionalLight {
    vec3 direction;
    vec3 ambient;
    vec3 diffuse;
    vec3 specular;
};

struct PointLight {
    vec3 position;
    vec3 ambient;
    vec3 diffuse;
    vec3 specular;
    float constant;
    float linear;
    float quadratic;
};

struct SpotLight {
    vec3 position;
    vec3 direction;
    vec3 ambient;
    vec3 diffuse;
    vec3 specular;
    float constant;
    float linear;
    float quadratic;
    float cutOff;
    float outerCutOff;
};

out vec4 color;

in GS_OUT
{
    vec3 v_Normal;
    vec2 v_TexCoord;
    vec3 v_FragPos;
} fs_in;

#define NR_POINT_LIGHTS 1 

uniform Material u_Material;
uniform DirectionalLight u_DirectionalLight;
uniform PointLight u_PointLights[NR_POINT_LIGHTS];
uniform SpotLight u_SpotLight;
uniform vec3 u_ViewPos;
uniform samplerCube skybox;

vec3 calculateDirectionalLight(DirectionalLight light, Material material, vec2 texCoord, vec3 normal, vec3 viewDirection);
vec3 calculatePointLight(PointLight light, Material material, vec2 texCoord, vec3 normal, vec3 fragPos, vec3 viewDirection);
vec3 calculateSpotLight(SpotLight light, Material material, vec2 texCoord, vec3 normal, vec3 fragPos, vec3 viewDirection);

void main()
{
    vec3 lightColor = vec3(0.0);
    vec3 normal = normalize(fs_in.v_Normal);
    vec3 viewDirection = normalize(u_ViewPos - fs_in.v_FragPos);

    lightColor += calculateDirectionalLight(u_DirectionalLight, u_Material, fs_in.v_TexCoord, normal, viewDirection);
    for (int i = 0; i < NR_POINT_LIGHTS; i++)
        lightColor += calculatePointLight(u_PointLights[i], u_Material, fs_in.v_TexCoord, normal, fs_in.v_FragPos, viewDirection);

    lightColor += calculateSpotLight(u_SpotLight, u_Material, fs_in.v_TexCoord, normal, fs_in.v_FragPos, viewDirection);

    lightColor += texture(u_Material.ambient, fs_in.v_TexCoord).rgb * texture(skybox, reflect(-viewDirection, normal)).rgb;

    color = vec4(lightColor, 1.0);
}

vec3 calculateDirectionalLight(DirectionalLight light, Material material, vec2 texCoord, vec3 normal, vec3 viewDirection)
{
    vec3 ambient = light.ambient * vec3(texture(material.diffuse, texCoord));

    vec3 lightDirection = normalize(-light.direction);
    vec3 diffuse = light.diffuse * vec3(texture(material.diffuse, texCoord)) * max(dot(lightDirection, normal), 0.0);

    vec3 reflectDirection = reflect(-lightDirection, normal);
    vec3 specular = light.specular * vec3(texture(material.specular, texCoord)) * pow(max(dot(viewDirection, reflectDirection), 0.0), material.shininess);

    // vec3 emmisive = texture(material.emmisive, texCoord).rgb;

    return vec3(ambient + diffuse + specular);
}

vec3 calculatePointLight(PointLight light, Material material, vec2 texCoord, vec3 normal, vec3 fragPos, vec3 viewDirection)
{
    vec3 ambient = light.ambient * vec3(texture(material.diffuse, texCoord));

    vec3 lightDirection = normalize(light.position - fragPos);
    vec3 diffuse = light.diffuse * vec3(texture(material.diffuse, texCoord)) * max(dot(lightDirection, normal), 0.0);

    vec3 reflectDirection = reflect(-lightDirection, normal);
    vec3 specular = light.specular * vec3(texture(material.specular, texCoord)) * pow(max(dot(viewDirection, reflectDirection), 0.0), material.shininess);

    float distance = length(light.position - fragPos);
    float attenuation = 1.0 / (light.constant + light.linear * distance +
        light.quadratic * (distance * distance));

    ambient  *= attenuation;
    diffuse  *= attenuation;
    specular *= attenuation;

    // vec3 emmisive = texture(material.emmisive, texCoord).rgb;

    return vec3(ambient + diffuse + specular);
}

vec3 calculateSpotLight(SpotLight light, Material material, vec2 texCoord, vec3 normal, vec3 fragPos, vec3 viewDirection)
{
    vec3 lightDirection = normalize(light.position - fragPos);
    float theta = dot(lightDirection, normalize(-light.direction));
    float epsilon = light.cutOff - light.outerCutOff;
    float intensity = clamp((theta - light.outerCutOff) / epsilon, 0.0, 1.0);

    vec3 ambient = light.ambient * vec3(texture(material.diffuse, texCoord));

    vec3 diffuse = light.diffuse * vec3(texture(material.diffuse, texCoord)) * max(dot(lightDirection, normal), 0.0);

    vec3 reflectDirection = reflect(-lightDirection, normal);
    vec3 specular = light.specular * vec3(texture(material.specular, texCoord)) * pow(max(dot(viewDirection, reflectDirection), 0.0), material.shininess);

    // vec3 emmisive = texture(material.emmisive, texCoord).rgb;

    float distance = length(light.position - fragPos);
    float attenuation = 1.0 / (light.constant + light.linear * distance +
        light.quadratic * (distance * distance));

    ambient  *= intensity * attenuation;
    diffuse  *= intensity * attenuation;
    specular *= intensity * attenuation;

    return vec3(ambient + diffuse + specular);
}

Before I've added the geometry shader and passed the interpolated vertex attributes through it: enter image description here

After passing varying attributes through the geometry shader: enter image description here

Any ideas what I'm missing?


Solution

  • gl_Position = explode(gl_in[2].gl_Position, normal);
    gs_out.v_Normal = gs_in[1].v_Normal;
    gs_out.v_TexCoord = gs_in[1].v_TexCoord;
    

    Looks like a copy paste error, you probably meant to put 2 here instead of 1.