I'm drawing my lines filled with a texture i'm repeating in my shader. As show below
The line are single points - that each vertex i'm expanding in my vertex shader with some calculation that always will be same pixel width no matter what zoom we are.
Than i'm creating my triangles and on them i'm drawing my texture repeatedly on the X axis. so the width of the line is always the image height.
The user can zoom in as much as he wants and the shapes getting bigger and smaller as zoom change. Although the texture saving it's size, means that there are more repeats.
When the user zoom in very much i'm starting to get strange results, i guess due to float overflow.
zoom:1
zoom 2
My shaders:
Vertex Shader
uniform float factor;
attribute vec2 texCoords;
varying vec2 vTexCoords;
attribute vec4 texAtlas;
varying vec4 vTexAtlas;
uniform vec4 uPixelWolrdScale;
attribute vec2 outlineOffset;
void main() {
vTexCoords = texCoords;
vTexAtlas = texAtlas;
gl_Position = LIGHTGLgl_ModelViewProjectionMatrix * (LIGHTGLgl_Vertex + uWorldOffset) + vec4((outlineOffset.xy) * uPixelWolrdScale.zw, 0,0);
}
uPixelWolrdScale is vec4 with the xy = worldScale.xy / ScreenSize.xy, zw = 2/ ScreenSize.xy.
I'm using the zw
for offseting the width of the line
and the xy for repeating my texture in the fragment shader
precision highp float;
uniform float factor;
uniform vec4 color;
varying vec2 vTexCoords;
uniform vec4 uPixelWolrdScale;
uniform sampler2D sampler;
varying vec4 vTexAtlas;
void main() {
// Here is the problem i guess
vec2 vexelPos = fract(vec2((vTexCoords.s) / (uPixelWolrdScale.x * factor), vTexCoords.t));
vexelPos = vTexAtlas.xy + vexelPos * vTexAtlas.zw;
gl_FragColor = texture2D(sampler, vexelPos);
gl_FragColor *= color;
}
vTexCoords.s
is the number of the repeats when the world and the screen is the same units. no zoom.
Is there another way to repeat the texture when (vTexCoords.s) / (uPixelWolrdScale.x * factor)
is overflowing?
-----EDITED ------
Tried to change my approach by using mod()
instead of fract()
for achieving repeats.
After few rounds I've managed to do this, as solution to my problem, but it is still in some zooms starting to freak.
The basic thought is to use homogeneous values for repeating the texture with a additional computing varying - with the help of the texture size and modulus.
In my vertex shader
I've added attribute and varying
attribute vec4 startVertex;
varying float vVertex;
...
// Same calculation i did to the gl_Vertex I do here to the attribute
vec4 coordToRemove = LIGHTGLgl_ModelViewProjectionMatrix * (startVertex + uWorldOffset) + vec4((outlineOffset.xy) * uPixelWolrdScale.zw, 0,0);
vVertex = gl_Position.x - coordToRemove.x;
I want my varying to start from 0 and interpolate all the way to the second homogeneous position. so I've added the first vertex value as an attribute for both vertices - coordForVar
- So when the first vertex will get here vVertex
will be 0. and the second vVertex
will be the difference.
In my fragment shader
varying float vVertex;
...
float hmgSize = 1. / 32.; // Getting the size in homogeneous - For now 32px, later uniform/attribute
vec2 vexelPos = vec2(mod(vVertex, hmgSize) / hmgSize, vTexCoords.t);
vexelPos = vTexAtlas.xy + vexelPos * vTexAtlas.zw;
vec2 uv = gl_FragCoord.xy/resolution;
gives you accurate pixel size, if it could help...(resolution is texture size) - j-presolution
is not part of WebGL itself, just some common environments.uPixelWolrdScale
is doing almost the same job here. - Kevin Reid#version ...
directive (optional) and aprecision ... float
statement (not optional in fragment shaders). I'd go withmediump
though chances are it will make no difference whatsoever in your typical WebGL implementation (most desktop hardware doesn't care about this). - Andon M. Colemanprecision highp float
is not guaranteed in fragment shaders in OpenGL ES 2.0 (WebGL). You would have to do some pre-processor tests to use it compliantly, but ES 2.0 does guaranteemediump
support so it's a good universal choice. Version, on the other hand, is completely optional and automatically assumed to be 100 by default in ES 2.0. There is no default floating-point precision in a fragment shader, which is why it's required. - Andon M. Coleman