I’m working on a Sandbox game at the moment and wanted to improve the rendering of the Chunks.
I started to work myself into greedy meshing and not long after that I implemented it and it works fine now, the problem i have is: the faces don’t all have the size of one Tile anymore, there’s faces that have 2x2 Tiles meshed into one and if i put the texture on it, well obviously it stretches to fill the whole area. I want to display it so that it repeats the texture so it looks like it looked before. this wouldn’t be a problem if the Tiles are all different textures ( i could just make the texcoord from 0 to 2 instead of from 0 to 1) but i have them all together in a spritesheet and no idea how i can repeat one part of it on a face.
I’ve read that i could write a fragment shader that uses modulo operations but i didn’t want to implement shaders for now, so is there any other option for this?
If you are willing to let go of your spritesheet, you can look at GL_TEXTURE_2D_ARRAY, where your texcoords have three dimensions (namely: u,v, layerIndex), where you pick your sprite with the layerIndex.
This allows repeating of sprites as per your demand. Limitation is that all sprites in the array must have the same dimensions, but with tile textures that’s common. A workaround would be scaling-up-to-fit, or using multiple texture arrays, if you have distinct sets of dimensions.
Shaders should be first thing that you learn when you start to fiddle with graphics programming.
i decided to go with the shaders (how difficult can that be?) since i don’t know how to use texture2darsays or how to implement them in VBOs.
Frag Shader:
varying vec3 vertNormal;
varying vec4 vertColor;
varying vec4 viewSpace;
uniform sampler2D tex;
void main(){
if(viewSpace.z==0){
vec4 texel = texture2D(tex,gl_TexCoord[0].st);
texel.r=texel.r*vertColor.r;
texel.g=texel.g*vertColor.g;
texel.b=texel.b*vertColor.b;
texel.a=texel.a*vertColor.a;
gl_FragColor = texel;
}else{
float x = gl_TexCoord[0].s*32-mod(gl_TexCoord[0].s*32,1);
float y = gl_TexCoord[0].t*32-mod(gl_TexCoord[0].t*32,1);
float fx = gl_TexCoord[0].s*32-x;
float fy = gl_TexCoord[0].t*32-y;
float tx = mod(fx*viewSpace.z,1);
if(tx<=0.001){tx=0.001;}
if(tx>=0.999){tx=0.999;}
float ty = mod(fy*viewSpace.z,1);
if(ty<=0.001){ty=0.001;}
if(ty>=0.999){ty=0.999;}
float finalx = (x+tx)/32;
float finaly = (y+ty)/32;
vec2 modded = vec2(finalx,finaly);
vec4 texel = texture2D(tex,modded);
texel.r=texel.r*vertColor.r;
texel.g=texel.g*vertColor.g;
texel.b=texel.b*vertColor.b;
texel.a=texel.a*vertColor.a;
gl_FragColor = texel;
}
}
}
Vert Shader:
varying vec3 vertNormal;
varying vec4 vertColor;
varying vec4 viewSpace;
void main(){
gl_Position = gl_ModelViewProjectionMatrix*gl_Vertex;
vertNormal = normalize(gl_NormalMatrix * gl_Normal);
vertColor = gl_Color;
viewSpace = gl_Vertex;
gl_TexCoord[0] = gl_MultiTexCoord0;
}
the result:
Some blue lines between (I could understand that for rounding issues or something)
and some brown/yellowish gradient which makes no sense for me (the texture doesn’t have this kind of gradient next to the grey texture)
in the vertex shader the 0.001 and 0.999 are there so the tex coordinates never belong to a nearby texture, i don’t understand where the problem lies :-\
Edit: I use the z coordinate to see how often the tile has to be repeated in the current face (1= normal, 2= it’s a 2x2 quad, 4= it’s a 4x4 quad)
Oh, god, the horror.
#version 110
varying vec3 vertNormal;
varying vec4 vertColor;
varying vec4 viewSpace;
uniform sampler2D tex;
void main(){
vec2 texCoords = gl_TexCoord[0].st;
if(viewSpace.z==0){
/*vec4 texel = texture2D(tex,gl_TexCoord[0].st);
texel.r=texel.r*vertColor.r;
texel.g=texel.g*vertColor.g;
texel.b=texel.b*vertColor.b;
texel.a=texel.a*vertColor.a;
gl_FragColor = texel;*/
gl_FragColor = vertColor * texture2D(tex, texCoords);
}else{
/*float x = gl_TexCoord[0].s*32-mod(gl_TexCoord[0].s*32,1);
float y = gl_TexCoord[0].t*32-mod(gl_TexCoord[0].t*32,1);
float fx = gl_TexCoord[0].s*32-x;
float fy = gl_TexCoord[0].t*32-y;*/
vec2 xy = floor(texCoords*32);
vec2 fxy = texCoords*32 - xy;
/*float tx = mod(fx*viewSpace.z,1);
if(tx<=0.001){tx=0.001;}
if(tx>=0.999){tx=0.999;}
float ty = mod(fy*viewSpace.z,1);
if(ty<=0.001){ty=0.001;}
if(ty>=0.999){ty=0.999;}*/
vec2 txy = clamp(fract(fxy * viewSpace.z), 0.001, 0.999);
/*float finalx = (x+tx)/32;
float finaly = (y+ty)/32;
vec2 modded = vec2(finalx,finaly);*/
vec2 modded = (xy+txy) / 32.0;
/*vec4 texel = texture2D(tex, modded);
texel.r=texel.r*vertColor.r;
texel.g=texel.g*vertColor.g;
texel.b=texel.b*vertColor.b;
texel.a=texel.a*vertColor.a;
gl_FragColor = texel;*/
gl_FragColor = vertColor * texture2D(tex, modded);
}
}
well, my first try at GLSL i don’t know that i can directly multiply vectors etc. :o
Even better version as there is it gets rid of one branch:
#version 110
varying vec3 vertNormal;
varying vec4 vertColor;
varying vec4 viewSpace;
uniform sampler2D tex;
void main(){
vec2 texCoords = gl_TexCoord[0].st;
if(viewSpace.z != 0.0){
vec2 xy = floor(texCoords*32);
vec2 fxy = texCoords*32 - xy;
vec2 txy = clamp(fract(fxy * viewSpace.z), 0.001, 0.999);
texCoords = (xy+txy) / 32.0;
}
gl_FragColor = vertColor * texture2D(tex, texCoords);
}
okey, but the problem with the lines is still there? :C
What kind of filtering do you use on the texture?
I use this in my texture init code:
GL11.glTexParameteri(GL11.GL_TEXTURE_2D, GL11.GL_TEXTURE_WRAP_S,GL11.GL_REPEAT);
GL11.glTexParameteri(GL11.GL_TEXTURE_2D, GL11.GL_TEXTURE_WRAP_T,GL11.GL_REPEAT);
GL11.glTexParameteri(GL11.GL_TEXTURE_2D, GL11.GL_TEXTURE_MAG_FILTER,GL11.GL_NEAREST);
GL11.glTexParameteri(GL11.GL_TEXTURE_2D, GL11.GL_TEXTURE_MIN_FILTER,GL11.GL_LINEAR_MIPMAP_LINEAR);
edit: using png decoder
Linear filtering can cause bleeding. Try to use GL_NEAREST for both.
that solved the problem, thx