Sphere heightmap displacement

Started by
0 comments, last by Rhakiras 10 years, 1 month ago

Hi, I have got to the point in my program where I have a tessellated sphere with a heightmap texture wrapped around it. My math however, is quite rusty and I'm struggling to figure out how to "push" each vertex out depending on the colour of the texture. I'm assuming its going to be a small change but I just can't figure it out.

Thanks in advance (Shaders/Image below)


-- VERTEX
#version 420 core

in vec3 position;

void main() {
    gl_Position = vec4(position, 1.0);
}


-- TCS
#version 420 core

layout(vertices = 3) out;

uniform float tessLevelInner;
uniform float tessLevelOuter;

void main(void){
    if (gl_InvocationID == 0) {
        gl_TessLevelInner[0] = tessLevelInner;
        gl_TessLevelOuter[0] = tessLevelOuter;
        gl_TessLevelOuter[1] = tessLevelOuter;
        gl_TessLevelOuter[2] = tessLevelOuter;
    }
    gl_out[gl_InvocationID].gl_Position = gl_in[gl_InvocationID].gl_Position;
}

-- TES
#version 420 core

layout(triangles, equal_spacing, cw) in;

uniform sampler2D heightmapTex;

uniform mat4 modelMatrix;
uniform mat4 viewMatrix;
uniform mat4 projMatrix;


out TES_OUT {
    vec3 worldPos;
} tes_out;

void main(void) {
    vec3 p0 = gl_TessCoord.x * gl_in[0].gl_Position;
    vec3 p1 = gl_TessCoord.y * gl_in[1].gl_Position;
    vec3 p2 = gl_TessCoord.z * gl_in[2].gl_Position;
    vec3 tePosition = normalize(p0 + p1 + p2);

    mat4 mvp = projMatrix * viewMatrix * modelMatrix; 
    
    gl_Position = mvp * vec4(tePosition, 1);
    
    tes_out.worldPos = gl_Position.xyz;
}

-- GEOMETRY
#version 420 core

#define M_PI 3.1415926535897932384626433832795

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

uniform mat4 modelMatrix;

out G_OUT {
    vec3 normal;
    vec2 texCoord;
} g_out;

void main(void) {
    mat3 normalMatrix = transpose(inverse(mat3(modelMatrix)));
    vec3 A = gl_in[2].gl_Position - gl_in[0].gl_Position;
    vec3 B = gl_in[1].gl_Position - gl_in[0].gl_Position;

    int i;
    for(i = 0; i < gl_in.length(); i++) {
        g_out.normal = normalMatrix * normalize(cross(A, B));
        
        // USE NORMALS TO WORK OUT TEXTURE UV COORDS
        g_out.texCoord = vec2(asin(g_out.normal.x) / M_PI + 0.5, asin(g_out.normal.y)/ M_PI + 0.5);
        
        gl_Position = gl_in[i].gl_Position;
        EmitVertex();
    }
}

-- FRAG
#version 420 core

uniform sampler2D heightmapTex;

uniform vec3 cameraPos;
uniform vec4 lightColour;
uniform vec3 lightPos;
uniform float lightRadius;

in G_OUT {
    vec3 normal;
    vec2 texCoord;
    vec3 worldPos;
} fs_in;

void main() {
	vec3 incident = normalize ( lightPos - fs_in.worldPos );
	vec3 viewDir = normalize ( cameraPos - fs_in.worldPos );
	vec3 halfDir = normalize ( incident + viewDir );
    
    float dist = length ( lightPos - fs_in.worldPos );
	float atten = 1.0 - clamp ( dist / lightRadius , 0.0 , 1.0);
    
    float lambert = max (0.0 , dot ( incident , fs_in.normal ));

	float rFactor = max (0.0 , dot ( halfDir , fs_in.normal ));
	float sFactor = pow ( rFactor , 50.0 );

    vec4 texCol = texture(heightmapTex, fs_in.texCoord);
	vec3 ambient = texCol.rgb * lightColour.xyz * 0.1;
	vec3 diffuse = texCol.rgb * lightColour.xyz * lambert * atten;
	vec3 specular = lightColour.xyz * sFactor * atten;


    // SHOW TEXTURE WITH LIGHTING
    gl_FragColor = vec4 ( ambient + diffuse + specular , texCol.a );
}
Advertisement

Asked too early tongue.png I just managed to solve my problem by calculating the normals and texture coords in the TES instead. Thanks, code below works:


-- TES
#version 420 core

#define M_PI 3.1415926535897932384626433832795

layout(triangles, equal_spacing, cw) in;

uniform mat4 modelMatrix;
uniform mat4 viewMatrix;
uniform mat4 projMatrix;
uniform sampler2D heightmapTex;

out TES_OUT {
    vec3 normal;
    vec2 texCoord;
} tes_out;

void main(void) {
    vec3 p0 = gl_TessCoord.x * gl_in[0].gl_Position;
    vec3 p1 = gl_TessCoord.y * gl_in[1].gl_Position;
    vec3 p2 = gl_TessCoord.z * gl_in[2].gl_Position;
    vec3 tePosition = normalize(p0 + p1 + p2);
    
    // CALCULATE NORMAL
    mat3 normalMatrix = transpose(inverse(mat3(modelMatrix)));
    tes_out.normal = mat3(normalMatrix) * normalize(p0 + p1 + p2);
    
    // USE NORMALS TO WORK OUT TEXTURE UV COORDS
    tes_out.texCoord = vec2(asin(tes_out.normal.x) / M_PI + 0.5, asin(tes_out.normal.y)/ M_PI + 0.5);

    // CALCULATE HEIGHT FROM TEX
    vec4 tex = texture(heightmapTex, tes_out.texCoord);
    float r = tex.r;
    vec4 heightmapPos = vec4(tes_out.normal * r, 0.0) + vec4(tePosition, 1);
    
    // SET FINAL MVP POSITION
    mat4 mvp = projMatrix * viewMatrix * modelMatrix; 
    gl_Position = mvp * heightmapPos;
}

-- GEOM
#version 420 core

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

in TES_OUT {
    vec3 normal;
    vec2 texCoord;
} g_in[];

out G_OUT {
    vec3 normal;
    vec2 texCoord;
    vec3 worldPos;
} g_out;

void main(void) {
    int i;
    for(i = 0; i < gl_in.length(); i++) {
        g_out.normal = g_in[i].normal;

        g_out.texCoord = g_in[i].texCoord;
        
        g_out.worldPos = gl_in[i].gl_Position;
        
        gl_Position = gl_in[i].gl_Position;
        
        EmitVertex();
    }
}

This topic is closed to new replies.

Advertisement