Advertisement Jump to content
Sign in to follow this  
Rhakiras

Sphere heightmap displacement

This topic is 1788 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

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

Share this post


Link to post
Share on other sites
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();
    }
}

Share this post


Link to post
Share on other sites
Sign in to follow this  

  • Advertisement
×

Important Information

By using GameDev.net, you agree to our community Guidelines, Terms of Use, and Privacy Policy.

GameDev.net is your game development community. Create an account for your GameDev Portfolio and participate in the largest developer community in the games industry.

Sign me up!