Hi, @Jack! Just wanted to show you an issue I may have found.
As you can see in the attached photo, I tested out with my own 1024x1024 texture set to the entire atlas as opposed to 256 x 256 texture tiles here :
Here is my main.agc :
SetErrorMode(0)
// set window properties
SetWindowTitle( "TerrainShader" )
SetWindowSize( 1280,720,0 )
SetWindowPosition(0,0)
// set display properties
SetVirtualResolution( 1920, 1080 )
SetOrientationAllowed( 1, 1, 1, 1 )
SetSyncRate( 60, 0 ) // 30fps instead of 60 to save battery
UseNewDefaultFonts( 1 ) // since version 2.0.22 we can use nicer default fonts
SetShadowMappingMode( 1 )
SetShadowBias(0.002)
SetShadowLightStepSize( 0.01 )
terrmask = LoadImage("2x2_TerrainAtlas_Alpha.png")
SetGenerateMipmaps( 1 )
// SetDefaultMagFilter( 0 ) //add this
// SetDefaultMinFilter( 0 ) //add this
floorshader = LoadShader("floor.vs","floor.ps")
floorimg = LoadImage("4x4_TerrainAtlas.png")
floorobj = CreateObjectPlane(100,100)
SetObjectShader(floorobj,floorshader)
SetObjectRotation(floorobj,90,0,0)
SetObjectImage(floorobj,floorimg,0)
SetObjectImage(floorobj,terrmask,1)
SetImageWrapU( floorimg, 1 ) //not sure if needed?
SetImageWrapV( floorimg, 1 ) //not sure if needed?
SetObjectReceiveShadow( floorobj, 1 )
AddVirtualButton(1,1800,64,64)
SetVirtualButtonSize(1,128,128)
SetVirtualButtonText(1,"Reload"+chr(10)+"Shader")
SetSunDirection( 0,-1,1 )
while ( GetRawKeyState ( 27 ) <> 1 )
print("WASD/Arrow Keys to move, Mouse to shift texture")
if GetVirtualButtonPressed(1)=1
// reload floor shader
floorshader = LoadShader("floor.vs","floor.ps")
SetObjectShader(floorobj,floorshader)
endif
// Handle left mouse button
if GetRawMouseLeftState()
px# = (GetPointerX()-tpx#)*0.00001
py# = (GetPointerY()-tpy#)*0.00001
print(px#)
print(py#)
SetShaderConstantByName(floorshader,"Mouse",-px#,-py#,0,0)
else
SetShaderConstantByName(floorshader,"Mouse",0.0,0.0,0,0)
endif
// handle right mouse button
if GetRawMouseRightState()
px# = (GetPointerX()-tpx#)*0.00001
py# = (GetPointerY()-tpy#)*0.00001
print(px#)
print(py#)
SetShaderConstantByName(floorshader,"Mouse2",-px#,-py#,0,0)
else
SetShaderConstantByName(floorshader,"Mouse2",0.0,0.0,0,0)
endif
// reset temp positions
if GetRawMouseLeftState()=0 and GetRawMouseRightState()=0
tpx# = GetPointerX()
tpy# = GetPointerY()
endif
HandleCameraMovement_FreeFlight(1.0,2.0)
Print( ScreenFPS() )
Sync()
endwhile
function HandleCameraMovement_FreeFlight(movespeed# as float, turnspeed# as float)
MoveCameraLocalZ(1,(GetRawKeyState(87)+GetRawKeyState(83)*-1) * movespeed#) // ws
MoveCameraLocalX(1,(GetRawKeyState(68)+GetRawKeyState(65)*-1) * movespeed#) // ad
RotateCameraLocalX(1,(GetRawKeyState(40)+GetRawKeyState(38)*-1)*turnspeed#)
RotateCameraGlobalY(1,(GetRawKeyState(39)+GetRawKeyState(37)*-1)*turnspeed#)
endfunction
Here is my floor.ps code :
/*
GLSL Terrain shader for a lot of unique textures on one frament.
This shader uses techniques like texture splatting and Altas image.
===================================================================
The special feature is the minimal required maps to create a terrain,
just one texture atlas map and one transparency atlas map. This
allows a lot of additional maps for shadows/ overlays/ decals or similar
The alpha map layer does use all color channels to represent the alpha
maps for the corresponding texture. It is also an atlas, if you go over four textures.
So a .PNG does contain four color channels RGBA. You can use each
channel to paint a texture layer.
Alpha image split calculation based on color map tiles:
1x1 => 1 tile * 4 channels = 4 alpha images *
2x2 => 4 tiles * 4 channels = 16 alpha images *
3x3 => 9 tiles * 4 channels = 36 alpha images
4x4 => 16 tiles * 4 channels = 64 alpha images *
....
(C) Online Arts 2017 - Alex Schmidt - Please don't steal
alex04.schmidt@gmail.com
Clamp modification by Golelorn
https://forum.thegamecreators.com/thread/222752
*/
uniform sampler2D texture0;
uniform sampler2D texture1;
varying highp vec3 posVarying;
varying mediump vec3 normalVarying;
varying highp vec2 uv0Varying;
varying highp vec2 uv1Varying;
varying mediump vec3 lightVarying;
uniform vec2 Mouse; // to visualize debug
uniform vec2 Mouse2; // to visualize debug
uniform vec2 agk_resolution; // this may be correct, but I don't really know, because of two textures
mediump vec3 GetPSLighting( mediump vec3 normal, highp vec3 pos );
mediump vec3 ApplyFog( mediump vec3 color, highp vec3 pointPos );
// color map container vars
float gridscale = 4.0; // how many times texture0 should be repeated on each dimension of the terrain (2x2, 4x4...)
float texscale = 4.0; // how many atlas images per dimension are in texture0 (2,0 = 2x2 = 4 sub images)
float tNorm = (1.0 / texscale) * 1.0;
int totalimages = int(texscale * texscale); // amount of total images as integer. In a 2x2 atlas it would be 4 - this defines mostly the structure of the alpha mask texture1
// alpha map container vars
float alphagridscale = 1.0; // how many times texture1 should be repeated on each dimension of the terrain
float alphatexscale = 2.0; // how many atlas images per dimension are in texture1
float alphatNorm = (1.0 / alphatexscale);
// initial vars
float pixelSize = (.5 / agk_resolution.x); // based on the actual image size
int alphaimage = 0; // the current or first alpha image to use
float Magic05 = 0.5; // I have to find out what it is meaning
void main()
{
// AGK lighting
mediump vec3 norm = normalize(normalVarying);
mediump vec3 light = lightVarying + GetPSLighting( norm, posVarying );
// care about the tiling of texture0 tiles
vec2 newuv = clamp( mod(uv0Varying * gridscale * Magic05, tNorm )+Mouse2, pixelSize,(1.0-pixelSize) );
// initial 'ground' layer aka first texture in atlas
highp vec3 color = texture2D(texture0, newuv).rgb ;
// care about the tiling of texture1 tiles
vec2 newuv2;
// texel alpha map preparation, use all four channels to get mask data. It can also be an atlas
// once you have more than a 2x2 color texture atlas, it will get quite complicated, as the image will be split and still contain the .rgba split aswell
// run a process for atlas image - each add all tiles together
for(int p=2;p<totalimages;p++){
int i = int( mod(float(p-2) , texscale) );
int alphatile = int( mod( float( ( (p-1) / int(texscale) ) ) , texscale) );
// find alpha tile
newuv2.x = clamp( (mod(uv0Varying.x * alphagridscale * alphatNorm, alphatNorm ) + mod( float(alphatile) , alphatexscale) * alphatNorm), pixelSize,(1.0-pixelSize) );
newuv2.y = clamp( (mod(uv0Varying.y * alphagridscale * alphatNorm, alphatNorm ) + mod( float( alphatile / int(alphatexscale) ) , alphatexscale) * alphatNorm),pixelSize,(1.0-pixelSize) );
// get alpha tile texel
vec4 texel = texture2D(texture1, newuv2);
// find color position
newuv.x = clamp( (mod(uv0Varying.x * gridscale * tNorm, tNorm ) + mod( float((p-1)), texscale) * tNorm)+Mouse.x, pixelSize,(1.0-pixelSize) );
newuv.y = clamp( (mod(uv0Varying.y * gridscale * tNorm, tNorm ) + mod( float( ( (p-1)/(int(texscale)) ) ), texscale) * tNorm)+Mouse.y, pixelSize,(1.0-pixelSize) );
// mix color map of texture atlas with corresponding alpha map of alpha atlas
color = mix(color.rgb, texture2D( texture0, newuv ).rgb,texel[i]*texel.a);
}
// AGK fog
color = ApplyFog( color, posVarying )* light;
// final output
gl_FragColor = vec4(color,1.0);
}
And I see a huge seam issue with it. Is there any way to fix this?
Also would be great to be able to control the repeat size of each texture in the Texture Atlas!
Thanks!