I have a hexagon tiled geometry I created in Blender
Which I then load in WebGL, using THREE.js library. Below is the loading code, I've cut the code of creating scene, lights, etc. I create rendered with antialiasing flag.
grassTexture = new THREE.ImageUtils.loadTexture( 'textures/GrassTileModo.png');
grassTexture.wrapS = grassTexture.wrapT = THREE.RepeatWrapping;
var loader = new THREE.JSONLoader();
loader.load("models/hexmap.json", function(geometry)
{
var attr = []
for(var i = 0; i < geometry.faces.length; i++)
{
if(i % 4 == 0)
att = [new THREE.Vector3(1.0, 0.0, 0.0), new THREE.Vector3(0.0, 1.0, 0.0), new THREE.Vector3(0.0, 0.0, 1.0)];
if(i % 4 == 1 || i % 4 == 2)
att = [new THREE.Vector3(1.0, 0.0, 0.0), new THREE.Vector3(0.0, 0.0, 1.0), new THREE.Vector3(0.0, 1.0, 0.0)];
if(i % 4 == 3)
att = [new THREE.Vector3(1.0, 1.0, 1.0), new THREE.Vector3(1.0, 1.0, 1.0), new THREE.Vector3(1.0, 1.0, 1.0)];
attr.push(att);
}
var material = new THREE.ShaderMaterial( {
uniforms:
{
diffuse: {type: 'c', value: new THREE.Color(1, 1, 1)},
opacity: {type: 'f', value: 1.0},
map: {type: 't', value: grassTexture},
},
attributes:
{
aBorderMap: {type: 'v3', value: attr, boundTo: 'faceVertices'}
},
vertexShader: document.getElementById('shader-vs').firstChild.textContent,
fragmentShader: document.getElementById('shader-fs').firstChild.textContent
} );
plane = new THREE.Mesh(geometry, material);
scene.add( plane );
});
Basically, the idea is I assign each vertex barycentric coords, and use them to know which edge I need to outline. Since my hexagons are getting tesselated by blender to 4 faces each, I assign different attributes to different faces, the way edges I don't need to outline are not outlined. In my case on the edges I don't want to outline, z barycentric coordinate will be zero.
This is how blender tesselates:
Vertex shader code:
precision highp float;
precision highp int;
uniform mat4 modelViewMatrix;
uniform mat4 projectionMatrix;
attribute vec3 position;
attribute vec2 uv;
varying vec2 vUv;
attribute vec3 aBorderMap;
varying vec3 vBorderMap;
void main()
{
vUv = uv;
vBorderMap = aBorderMap;
vec4 mvPosition;
mvPosition = modelViewMatrix * vec4( position, 1.0 );
gl_Position = projectionMatrix * mvPosition;
}
Fragment shader code:
precision highp float;
precision highp int;
uniform vec3 diffuse;
uniform float opacity;
varying vec2 vUv;
uniform sampler2D map;
varying vec3 vBorderMap;
void main()
{
gl_FragColor = vec4( diffuse, opacity );
vec4 texelColor;
if(vBorderMap.x <= 0.05 || vBorderMap.y <= 0.05)
texelColor = texture2D( map, vUv ) * 0.5 + vec4(0.0, 0.0, 0.0, 1.0) * 0.5;
else
texelColor = texture2D( map, vUv );
gl_FragColor = gl_FragColor * texelColor;
}
When I zoom out those artifacts can be clearly seen:
Although zoomed in it looks much better:
At first I thought lack of antialaising was a problem, but when I added it, it didn't help.
EDIT:
js fiddle link ---> https://jsfiddle.net/denisve/ad74pf77/5/
full screen ---> https://jsfiddle.net/denisve/ad74pf77/5/embedded/result/
WARNING: Huge embedded image there, so will take some time to load, sorry about that, didn't find a way to use external images on jsfiddle.