124 lines
3.1 KiB
Lua
124 lines
3.1 KiB
Lua
local love = assert( love )
|
|
local ffi = require( "ffi" )
|
|
local sideLength = 128 --VERTICES in a side
|
|
local vertexCount = sideLength * sideLength
|
|
local vertices = love.data.newByteData( 4 * 2 * vertexCount )
|
|
|
|
local heightMap = love.image.newImageData( "tex/terrain.jpg" )
|
|
local heightTex = love.graphics.newImage( heightMap, {linear = true} )
|
|
heightTex:setWrap( "repeat", "repeat" )
|
|
|
|
local mesh = love.graphics.newMesh(
|
|
{{"VertexPosition", "float", 2 }},
|
|
vertexCount,
|
|
"triangles",
|
|
"static"
|
|
)
|
|
|
|
--set vertices
|
|
do
|
|
local p = vertices:getFFIPointer()
|
|
local ptr = ffi.cast( "float*", p )
|
|
local i = 0
|
|
for x = 0, sideLength-1 do for y = 0, sideLength-1 do
|
|
ptr[i],ptr[i+1] = x - sideLength / 2 ,y - sideLength / 2
|
|
i=i+2
|
|
end end
|
|
mesh:setVertices( vertices )
|
|
do local _ = p end
|
|
end
|
|
|
|
--set vertex map
|
|
do
|
|
local ptr = {}
|
|
local n = 1
|
|
local s = sideLength
|
|
for x = 1, sideLength - 1 do for y = 0, sideLength - 2 do
|
|
local i = y*s+x
|
|
--print( x, y, i, i+1, i+s, i+s+1 )
|
|
ptr[n],ptr[n+1],ptr[n+2] = i,i+1,i+s
|
|
n=n+3
|
|
ptr[n],ptr[n+1],ptr[n+2] = i+1,s+i+1,i+s
|
|
n=n+3
|
|
end end
|
|
mesh:setVertexMap( ptr )
|
|
end
|
|
|
|
local shader = love.graphics.newShader[[
|
|
#define fog vec4( 0.6, 0.6, 0.7, 1.0 )
|
|
#define fogHigh vec4( 1.0, 1.0, 0.9, 1.0 )
|
|
#define fogFalloff 0.03
|
|
varying vec2 uv;
|
|
varying vec3 world;
|
|
varying vec3 normal;
|
|
varying float depth;
|
|
#ifdef VERTEX
|
|
uniform sampler2D height;
|
|
uniform mat4 view;
|
|
uniform mat4 proj;
|
|
|
|
float sigmoid( float x ){
|
|
return 1.0 / ( 1.0 + exp( -x ) );
|
|
}
|
|
|
|
vec4 position( mat4 _, vec4 pos ){
|
|
pos = pos.xzyw;
|
|
float y = Texel( height, pos.xz / 256.0 ).r - 0.5;
|
|
uv = 0.25 * (pos.xz + vec2(y, sin( y ) ));
|
|
float r = dot( pos.xz, pos.xz );
|
|
pos.y = sigmoid( r / 50.0 - 20.0 ) * ( 1.0 + y ) * 0.05 * r / (sqrt( r ) + 1) - 0.01;
|
|
|
|
world = pos.xyz;
|
|
vec4 eye = view*pos;
|
|
depth = clamp( -eye.z * fogFalloff, 0.0, 1.0 );
|
|
|
|
normal = vec3( 0.0, 1.0, 0.0 ) + 1.5 * pos.y ;
|
|
|
|
return proj*eye;
|
|
}
|
|
#endif
|
|
#ifdef PIXEL
|
|
uniform vec3 light;
|
|
vec4 effect( vec4 color, Image tex, vec2 texuv, vec2 scruv) {
|
|
|
|
vec3 albedo = 0.2 * Texel( tex, uv ).rgb;
|
|
|
|
//diffuse light
|
|
vec3 norm = normalize( normal );
|
|
vec3 toLight = normalize( light - world.xyz );
|
|
float diff = max( dot( norm, light ), 0.1 );
|
|
vec4 d = vec4( diff * albedo, 1.0 );
|
|
|
|
return mix( color * d , fog, depth );
|
|
}
|
|
#endif
|
|
]]
|
|
|
|
--set texture
|
|
do
|
|
local tex = love.graphics.newImage( "tex/rock.png", {mipmaps = true} )
|
|
tex:setWrap( "repeat", "repeat" )
|
|
mesh:setTexture( tex )
|
|
end
|
|
|
|
shader:send( "height", heightTex )
|
|
|
|
local obj = {}
|
|
|
|
local function worldSpaceToTexCoord( x, z )
|
|
return x, z
|
|
end
|
|
|
|
function obj.getHeight( x, z )
|
|
return heightMap:getPixel( worldSpaceToTexCoord(x,z) )[1]
|
|
end
|
|
|
|
function obj.draw( view, proj, light )
|
|
shader:send( "view", "column", view )
|
|
shader:send( "proj", "column", proj )
|
|
shader:send( "light", light )
|
|
love.graphics.setShader( shader )
|
|
love.graphics.draw( mesh )
|
|
end
|
|
|
|
return obj |