After torturing you with a walk-through of my terrain vertex shader I will do the same harm again, this time using the fragment shader... Without further ado, here we go:
#version 400 //Uniforms uniform sampler2D texture0;//diffuse map uniform sampler2D texture1;//normal map
After the obligatory version information, this time two texture uniforms are declared, the (already used) diffuse map and an additional normal map.
//Inputs in vec2 ex_texcoords0; in vec4 ex_color; in mat3 nmat;
Using that "naming-convention trick", three variables of the vertex shader are wired into the fragment shader, namingly the UV coordinates, the vertex color and the matrix for transforming normals into view space.
out vec4 fragData0; out vec4 fragData1; out vec4 fragData2; out vec4 fragData3;
And now I have to take a deeper breath: Leadwerks 3.1 is using a deferred renderer. This means that all lighting calculations are done behind the scenes in a separate processing step taking place after the fragment shader has run. So you won't see lighting calculations for diffuse reflection, specular reflection etc. here, but rather a filling-up of several buffers:
- fragData0 contains the diffuse color (rgb) and transparency (alpha) of the fragment
- fragData1 stores the normal (rgb) and specularity (alpha)
- fragData2 holds the emissive color (rgb) and a flag for lighting on/off (alpha)
- fragData3 - no idea if this is being used and what it might hold
vec4 outcolor = ex_color;
That's it for the ouverture, now into the main play. The vertex color is passed to the outcolor variable. Actually, the result up to here would look something like this:
An amorphous white mass with holes in it. Those holes are the cracks described earlier, caused by T-junctions between mesh levels. Hopefully, this can later be healed by a healthy dose of tessellation potion.
outcolor *= vec4((texture(texture0,ex_texcoords0)).xyz, 1.0); fragData0 = outcolor;
To make things a bit more interesting, the outcolor is multiplied by a sample of the diffuse map (retrieved using our self-calculated, global UV coordinates). The result is then stored in the diffuse buffer.
vec3 normal = texture(texture1,ex_texcoords0).xzy * 2.0 - 1.0; normal = normalize(nmat*normal); fragData1 = vec4(normal*0.5+0.5,0.0);
A bit more code - the normal map is sampled and "extended". Since a texture can store values between 0.0 and 1.0, but every (xyz) component of a normal can range from -1 to +1, those sampled values have to be brought into that range. The normal is transformed into view space, normalized again and stored in the normal buffer (back to a range of 0.0 to 1.0). The specularity is set to 0.0.
int materialflags=1; fragData2 = vec4(0.0,0.0,0.0,materialflags/255.0);
No emission, and setting the lighting flag to on. And here we go, the final result of our labor:
What's next?
I'll try to heal those cracks using tessellation, and I'll probably need some time to figure this out. To win that time, the next post will be about the general structure of a (pass-through) tessellation shader.
PS: Of course the entry images to these two posts were done using klepto2's and shadmar's wonderful Posteffect Pack. Thanks you two!
- 8
2 Comments
Recommended Comments