ring/src/models/terrain.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