#version 450 core layout(binding = 0) uniform sampler2D heightTexture; layout(binding = 1) uniform sampler2D colorTexture; in TE_OUT { vec3 position; vec2 texCoord; vec3 normal; } fs_in; layout(location = 0) out vec4 albedoGbuffer; layout(location = 1) out vec4 positionGbuffer; layout(location = 2) out vec4 normalGbuffer; float getHeight(vec2 uv) { return texture(heightTexture, uv).r * 0.025f; } vec3 calculateNormalsFromHeightTexture() { // Calculate height at base_uv float height = getHeight(fs_in.texCoord); // Calculate normals using height differences around the fragment float eps = 1.0f / textureSize(heightTexture, 0).x; float hRight = getHeight(fs_in.texCoord + vec2(eps, 0.0)); float hLeft = getHeight(fs_in.texCoord - vec2(eps, 0.0)); float hUp = getHeight(fs_in.texCoord + vec2(0.0, eps)); float hDown = getHeight(fs_in.texCoord - vec2(0.0, eps)); float heightTL = getHeight(fs_in.texCoord + vec2(-eps, eps)); float heightT = getHeight(fs_in.texCoord + vec2( 0.0, eps)); float heightTR = getHeight(fs_in.texCoord + vec2( eps, eps)); float heightL = getHeight(fs_in.texCoord + vec2(-eps, 0.0)); float heightR = getHeight(fs_in.texCoord + vec2( eps, 0.0)); float heightBL = getHeight(fs_in.texCoord + vec2(-eps, -eps)); float heightB = getHeight(fs_in.texCoord + vec2( 0.0, -eps)); float heightBR = getHeight(fs_in.texCoord + vec2( eps, -eps)); float sobelX = (heightTL + 2.0 * heightL + heightBL) - (heightTR + 2.0 * heightR + heightBR); float sobelZ = (heightTL + 2.0 * heightT + heightTR) - (heightBL + 2.0 * heightB + heightBR); vec3 tangentX = normalize(vec3(eps, 0.0, sobelX)); vec3 tangentZ = normalize(vec3(0.0, sobelZ, eps)); // Final normal for the fragment return normalize(cross(tangentZ, tangentX)); } void main() { albedoGbuffer = texture(colorTexture, vec2(fs_in.texCoord.x, -fs_in.texCoord.y)); positionGbuffer = vec4(fs_in.position, 1.0f); normalGbuffer = vec4(fs_in.normal, 1.0f); }