diff --git a/src/level/world.lua b/src/level/world.lua index 56efaf5..09e3912 100644 --- a/src/level/world.lua +++ b/src/level/world.lua @@ -12,6 +12,10 @@ local sky local bell local contempra local terrain +local spike +local water +local building +local veil local light = require( "level.light" ) function t.start() @@ -21,10 +25,14 @@ function t.start() depth = true, } + veil = require( "models.veil" ) + building = require( "models.building" ) +-- water = require( "models.water" ) sky = require( "models.sky" ) bell = require( "models.bell" ) contempra = require( "models.contempra" ) terrain = require( "models.terrain" ) + spike = require( "models.spike" ) end function t.debug() @@ -41,7 +49,7 @@ local function matte( ) end end -function t.draw( view, proj ) +function t.draw( view, proj, player ) if isDebugging then end @@ -56,9 +64,12 @@ function t.draw( view, proj ) love.graphics.setMeshCullMode( "back" ) sky.draw( view, proj, light ) - terrain.draw( view, proj ) + terrain.draw( view, proj, light ) + building.draw( view, proj, light ) bell.draw( view, proj, light ) contempra.draw( view, proj, light ) + spike.draw( view, proj, light ) + veil.draw( view, proj ) love.graphics.pop() diff --git a/src/models/bell.lua b/src/models/bell.lua index 327f6cf..79db485 100644 --- a/src/models/bell.lua +++ b/src/models/bell.lua @@ -111,7 +111,7 @@ do local c, s = math.cos( 2*math.pi / 7 ), -math.sin( 2*math.pi / 7 ) local x, z = 1, 0 - local r = 15 + local r = 40 for i = 1, 7 do bells[i] = { i / 2, r * x, r * z, (i-1)/6 } x, z = c*x+s*z, c*z-s*x @@ -128,6 +128,7 @@ t.mesh = bellMesh function t.draw( view, proj, light ) local s = t.shader + love.graphics.setColor(1,1,1,1) s:send( "view", "column", view ) s:send( "proj", "column", proj ) s:send("light", light ) diff --git a/src/models/building.bin b/src/models/building.bin new file mode 100644 index 0000000..35578f8 Binary files /dev/null and b/src/models/building.bin differ diff --git a/src/models/building.gltf b/src/models/building.gltf new file mode 100644 index 0000000..c2c47dc --- /dev/null +++ b/src/models/building.gltf @@ -0,0 +1,96 @@ +{ + "asset":{ + "generator":"Khronos glTF Blender I/O v4.2.70", + "version":"2.0" + }, + "scene":0, + "scenes":[ + { + "name":"Scene", + "nodes":[ + 0 + ] + } + ], + "nodes":[ + { + "mesh":0, + "name":"Building", + "translation":[ + 0, + 1, + 0 + ] + } + ], + "meshes":[ + { + "name":"Building", + "primitives":[ + { + "attributes":{ + "POSITION":0, + "NORMAL":1 + }, + "indices":2 + } + ] + } + ], + "accessors":[ + { + "bufferView":0, + "componentType":5126, + "count":643, + "max":[ + 10.494050979614258, + 2.4390439987182617, + 10.381834983825684 + ], + "min":[ + -9.749046325683594, + -0.9988071918487549, + -10.38186264038086 + ], + "type":"VEC3" + }, + { + "bufferView":1, + "componentType":5126, + "count":643, + "type":"VEC3" + }, + { + "bufferView":2, + "componentType":5123, + "count":999, + "type":"SCALAR" + } + ], + "bufferViews":[ + { + "buffer":0, + "byteLength":7716, + "byteOffset":0, + "target":34962 + }, + { + "buffer":0, + "byteLength":7716, + "byteOffset":7716, + "target":34962 + }, + { + "buffer":0, + "byteLength":1998, + "byteOffset":15432, + "target":34963 + } + ], + "buffers":[ + { + "byteLength":17432, + "uri":"building.bin" + } + ] +} diff --git a/src/models/building.lua b/src/models/building.lua index e69de29..36eb2bd 100644 --- a/src/models/building.lua +++ b/src/models/building.lua @@ -0,0 +1,94 @@ +local dkjson = require( "lib.dkjson" ) +local love = assert( love ) +local shader = require( "shaders.flat" ) +local mat = require( "mat4" ) + +local attributeNames = { + POSITION = "VertexPosition", + NORMAL = "VertexNormal", +} + +local types = { + ["SCALAR"] = 1, + ["VEC3"] = 3, +} + +local componentTypes = { + [5121] = "byte", + [5123] = "unorm16", + [5126] = "float", +} + +local elementComponentTypes = { + [5123] = "uint16", + [5126] = "uint32", +} + +local asset +local buffer +do + local fd = assert( love.filesystem.newFileData( "models/building.gltf" ) ) + asset = dkjson.decode( fd:getString() ) + buffer = love.filesystem.newFileData( "models/building.bin" ) +end + +--load all the bufferViews +local bufferViews = {} +for i, view in pairs( asset.bufferViews ) do + bufferViews[i] = love.data.newByteData( buffer, view.byteOffset, view.byteLength ) +end + +local function attributeFormat( attributeName, accessor ) + return {attributeNames[attributeName], componentTypes[accessor.componentType], types[accessor.type] } +end + +local function lgMesh( primitive ) + assert( not( primitive.mode ) ) --triangles only + + local finalMesh + for name, accIdx in pairs( primitive.attributes ) do + local acc = asset.accessors[accIdx+1] + + local mesh = love.graphics.newMesh( + {attributeFormat(name, acc)}, --vertexformat + acc.count, + "triangles", + "static" + ) + + local bfv = bufferViews[1+acc.bufferView] + mesh:setVertices( bfv ) + + if finalMesh then + finalMesh:attachAttribute( attributeNames[name], mesh ) + else + finalMesh = mesh + end + + end + + + do + local acc = asset.accessors[1+primitive.indices] + local bfv = bufferViews[1+acc.bufferView] + finalMesh:setVertexMap(bfv, elementComponentTypes[acc.componentType] ) + end + return finalMesh +end + +local obj = {} +local mesh = lgMesh( asset.meshes[1].primitives[1] ) +local id = mat.TRS(2,2,2,0,0,0,0,2,0) + +function obj.draw( view, proj, light ) + love.graphics.setMeshCullMode( "none" ) + shader:send( "view", "column", view ) + shader:send( "proj", "column", proj ) + shader:send( "light", light ) + love.graphics.setShader( shader ) + love.graphics.setColor( 0.05,0.05,0.1,1.0 ) + shader:send( "mdl", "column", id ) + love.graphics.draw( mesh ) +end + +return obj \ No newline at end of file diff --git a/src/models/contempra.lua b/src/models/contempra.lua index 4c55fac..c689885 100644 --- a/src/models/contempra.lua +++ b/src/models/contempra.lua @@ -115,7 +115,6 @@ local colors = setmetatable( ) function obj.draw( view, proj, light ) - love.graphics.setMeshCullMode( "none" ) --debug shader:send( "view", "column", view ) shader:send( "proj", "column", proj ) shader:send( "light", light ) diff --git a/src/models/gltf.lua b/src/models/gltf.lua new file mode 100644 index 0000000..e69de29 diff --git a/src/models/spike.bin b/src/models/spike.bin new file mode 100644 index 0000000..f4d98d4 Binary files /dev/null and b/src/models/spike.bin differ diff --git a/src/models/spike.gltf b/src/models/spike.gltf new file mode 100644 index 0000000..4b54463 --- /dev/null +++ b/src/models/spike.gltf @@ -0,0 +1,104 @@ +{ + "asset":{ + "generator":"Khronos glTF Blender I/O v4.2.70", + "version":"2.0" + }, + "scene":0, + "scenes":[ + { + "name":"Scene", + "nodes":[ + 0 + ] + } + ], + "nodes":[ + { + "mesh":0, + "name":"Spike" + } + ], + "meshes":[ + { + "name":"Spike", + "primitives":[ + { + "attributes":{ + "POSITION":0, + "NORMAL":1, + "TEXCOORD_0":2 + }, + "indices":3 + } + ] + } + ], + "accessors":[ + { + "bufferView":0, + "componentType":5126, + "count":48, + "max":[ + 1, + 1, + 1 + ], + "min":[ + -1, + 0, + -1 + ], + "type":"VEC3" + }, + { + "bufferView":1, + "componentType":5126, + "count":48, + "type":"VEC3" + }, + { + "bufferView":2, + "componentType":5126, + "count":48, + "type":"VEC2" + }, + { + "bufferView":3, + "componentType":5123, + "count":48, + "type":"SCALAR" + } + ], + "bufferViews":[ + { + "buffer":0, + "byteLength":576, + "byteOffset":0, + "target":34962 + }, + { + "buffer":0, + "byteLength":576, + "byteOffset":576, + "target":34962 + }, + { + "buffer":0, + "byteLength":384, + "byteOffset":1152, + "target":34962 + }, + { + "buffer":0, + "byteLength":96, + "byteOffset":1536, + "target":34963 + } + ], + "buffers":[ + { + "byteLength":1632, + "uri":"spike.bin" + } + ] +} diff --git a/src/models/spike.lua b/src/models/spike.lua index c845a2a..b24ab46 100644 --- a/src/models/spike.lua +++ b/src/models/spike.lua @@ -35,9 +35,9 @@ local filterTypes = { local asset local buffer do - local fd = assert( love.filesystem.newFileData( "models/bell.gltf" ) ) + local fd = assert( love.filesystem.newFileData( "models/spike.gltf" ) ) asset = dkjson.decode( fd:getString() ) - buffer = love.filesystem.newFileData( "models/bell.bin" ) + buffer = love.filesystem.newFileData( "models/spike.bin" ) end --load all the bufferViews @@ -70,43 +70,76 @@ local function lgMesh( primitive ) local finalMesh for name, accIdx in pairs( primitive.attributes ) do local acc = asset.accessors[accIdx+1] - + local mesh = love.graphics.newMesh( {attributeFormat(name, acc)}, --vertexformat acc.count, "triangles", "static" ) - + local bfv = bufferViews[1+acc.bufferView] mesh:setVertices( bfv ) - + if finalMesh then finalMesh:attachAttribute( attributeNames[name], mesh ) else finalMesh = mesh end - + end - - + + do local acc = asset.accessors[1+primitive.indices] local bfv = bufferViews[1+acc.bufferView] finalMesh:setVertexMap(bfv, elementComponentTypes[acc.componentType] ) end - + if primitive.material then finalMesh:setTexture( lgTexture( primitive.material ) ) end return finalMesh end local spike = lgMesh( asset.meshes[1].primitives[1] ) -local spikeInstanceMesh = {} +spike:setTexture( love.graphics.newImage( "tex/rock.png", { mipmaps = true } ) ) -local spikes = {} +local spikeCount = 4096 +do -function spikes.draw( view, proj, light ) - + local function rad(x,z) + return x*x+z*z + end + + local spikes = {} + local inner, outer = 25, 100 + for n = 1, spikeCount do + local r, a = math.sqrt( math.random() * (outer*outer-inner*inner)+outer*outer ), 2 * math.pi * math.random() + local x, z = r*math.cos(a),r*math.sin(a) + local h = 2 + 10 * math.random() + spikes[n] = { x, -1, z, h, 0 } + n=n+1 + end + local spikeInstanceMesh = love.graphics.newMesh( + {{"spikeInstance", "float", 4}, + {"spikeOrientation", "float", 1 }, + }, --vertexformat + spikes, + nil, + "static" + ) + spike:attachAttribute( "spikeInstance", spikeInstanceMesh, "perinstance" ) + spike:attachAttribute( "spikeOrientation", spikeInstanceMesh, "perinstance" ) end +local spikes = {} +function spikes.draw( view, proj, light ) + love.graphics.setColor( 1,1,1,1) + shader:send( "view", "column", view ) + shader:send( "proj", "column", proj ) + shader:send( "light", light ) + love.graphics.setShader( shader ) + love.graphics.drawInstanced( spike, spikeCount ) +end + + return spikes \ No newline at end of file diff --git a/src/models/terrain.lua b/src/models/terrain.lua index 139d268..69f470e 100644 --- a/src/models/terrain.lua +++ b/src/models/terrain.lua @@ -1,69 +1,116 @@ local love = assert( love ) local ffi = require( "ffi" ) -local sideLength = 256 +local sideLength = 128 --VERTICES in a side local vertexCount = sideLength * sideLength -local vertices = love.data.newByteData( 4 * vertexCount ) -local vertexMap = love.data.newByteData( 2 * vertexCount ) +local vertices = love.data.newByteData( 4 * 2 * vertexCount ) -local height = love.graphics.newImage( "tex/terrain.png" ) +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", 1 }}, + {{"VertexPosition", "float", 2 }}, vertexCount, - "strip", + "triangles", "static" ) -mesh:setTexture( height ) +--set vertices do - local p = vertexMap:getFFIPointer() - local ptr = ffi.cast( "uint16_t *", p) - for i = 0, vertexCount - 1 do - ptr[i] = i - end - mesh:setVertexMap( vertexMap, "uint16" ) - do local _ = p end --keep alive? + 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[[ - #pragma glsl3 - #define fog vec4( 0.85, 0.85, 1.0, 1.0 ) + #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; -//varying vec3 normal; - varying vec4 world; #ifdef VERTEX + uniform sampler2D height; uniform mat4 view; uniform mat4 proj; -// attribute vec3 VertexNormal; vec4 position( mat4 _, vec4 pos ){ -//normal = VertexNormal; - world = pos; - vec4 eye = view * world; - depth = -eye.z; + pos = pos.xzyw; + float y = Texel( height, pos.xz / 256.0 ).r - 0.5; + uv = 0.25 * (pos.xz + vec2(y, sin( y ) )); + pos.y += y; + + 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; + uniform vec3 light; vec4 effect( vec4 color, Image tex, vec2 texuv, vec2 scruv) { -// vec3 norm = normalize( normal ); -// vec3 toLight = normalize( light - world.xyz ); -// float diff = max( dot( norm, light ), 0.5 ); -// vec4 mainColor = vec4( diff * color.rgb, color.a ); - return mix( mix( color * Texel( tex, texuv ), fog, - clamp( depth / 80.0, 0.0, 1.0)), fogHigh, - clamp( world.y / 20.0, 0.0, 1.0)) ; + 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 ]] -local obj = { height = height } +--set texture +do + local tex = love.graphics.newImage( "tex/rock.png", {mipmaps = true} ) + tex:setWrap( "repeat", "repeat" ) + mesh:setTexture( tex ) +end -function obj.draw( view, proj ) +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 diff --git a/src/models/veil.lua b/src/models/veil.lua new file mode 100644 index 0000000..6aedaa3 --- /dev/null +++ b/src/models/veil.lua @@ -0,0 +1,43 @@ +local lg = love.graphics +local mesh = lg.newMesh( + {{"VertexPosition", "float", 3}}, + { + {-1,-1,-1}, --A + {-1,-1, 1}, --B + {-1, 1,-1}, --H + {-1, 1, 1}, --G + { 1,-1,-1}, --D + { 1,-1, 1}, --C + { 1, 1,-1}, --E + { 1, 1, 1}, --F + }, + "triangles", + "static") +mesh:setVertexMap{ + 1, 2, 3, + 2, 3, 4, + 3, 4, 7, + 4, 7, 8, + 7, 5, 8, + 5, 8, 6, + 8, 4, 6, + 4, 6, 2, + 6, 2, 5, + 2, 5, 1, + 5, 1, 7, + 1, 7, 3, +} + +local shader = require( "shaders.veil" ) + +local function draw( view, proj ) + lg.push( "all" ) + lg.setMeshCullMode( "none" ) + --get view matrix without translation + shader:send( "proj", "column", proj ) + shader:send( "view", "column", view ) + lg.setShader( shader ) + lg.draw( mesh ) + lg.pop() +end +return { draw = draw } \ No newline at end of file diff --git a/src/scenes/main.lua b/src/scenes/main.lua index f391ccb..1dc03bf 100644 --- a/src/scenes/main.lua +++ b/src/scenes/main.lua @@ -27,7 +27,7 @@ end function t.draw() - world.draw( player.view, player.proj ) + world.draw( player.view, player.proj, player.x, player.z ) local y = 0 for k, v in pairs(love.graphics.getStats()) do diff --git a/src/shaders/bell.lua b/src/shaders/bell.lua index 39431e0..f6a0f61 100644 --- a/src/shaders/bell.lua +++ b/src/shaders/bell.lua @@ -13,7 +13,7 @@ return love.graphics.newShader[[ uniform mat4 view; uniform mat4 proj; vec4 position( mat4 _, vec4 pos ){ - normal = (view*vec4(VertexNormal,1.0)).rgb; + normal = VertexNormal; instanceColor = bellInstance.a; pos.xyz *= bellInstance.r; pos.xz += bellInstance.gb; @@ -32,15 +32,17 @@ return love.graphics.newShader[[ float y = texuv.y; y = max( 0.1, 1.4 * pow( 0.9*y*(1.0-0.9*y) , 0.25)); - texel.rgb *= y; - texel.gb *= 0.5 * instanceColor + 0.75; + vec3 albedo = texel.rgb * y; + albedo.gb *= 0.5 * instanceColor + 0.75; //diffuse light vec3 norm = normalize( normal ); vec3 toLight = normalize( light - world.xyz ); - float diff = max( dot( norm, light ), 0.1 ); - vec4 mainColor = vec4( diff * texel.rgb, texel.a ); + float diff = max( dot( norm, light ), 0.5 ); + + vec4 mainColor = vec4( diff * albedo, texel.a ); + return color * mix( mix( mainColor, fog, clamp( depth / 80.0, 0.0, 1.0)), diff --git a/src/shaders/spike.lua b/src/shaders/spike.lua index e69de29..70d729a 100644 --- a/src/shaders/spike.lua +++ b/src/shaders/spike.lua @@ -0,0 +1,46 @@ +return love.graphics.newShader[[ + #define fog vec4( 0.6, 0.6, 0.7, 1.0 ) + #define fogHigh vec4( 0.7, 0.7, 0.6, 1.0 ) + #define sunDir 0.1 * vec3( 0.9, 0.2, 0.5 ) + varying float depth; + varying vec3 normal; + varying vec4 world; +#ifdef VERTEX + //per instance: (uniform) x, y, z, height + attribute vec4 spikeInstance; + attribute float spikeOrientation; + attribute vec3 VertexNormal; + uniform mat4 view; + uniform mat4 proj; + vec4 position( mat4 _, vec4 pos ){ + normal = VertexNormal; + pos.xz *= 0.25; + pos.y *= spikeInstance.w; + pos.xyz += spikeInstance.xyz; + world = pos; + + vec4 eye = view * pos; + depth = -eye.z; + return proj*eye; + } +#endif +#ifdef PIXEL + uniform vec3 light; + vec4 effect( vec4 color, Image tex, vec2 texuv, vec2 scruv) { + vec2 uv = vec2(texuv.x, texuv.y/10.0); + vec4 texel = Texel( tex, uv ); + + //diffuse light + vec3 norm = normalize( normal ); + vec3 toLight = normalize( light - world.xyz ); + float diff = max( dot( norm, light ), 0.1 ); + + vec4 mainColor = vec4( diff * texel.rgb, texel.a ); + + + return color * mix( mix( mainColor, + fog, clamp( depth / 80.0, 0.0, 1.0)), + fogHigh, clamp(world.y / 20.0, 0.0, 1.0)); + } +#endif +]] \ No newline at end of file diff --git a/src/shaders/veil.lua b/src/shaders/veil.lua new file mode 100644 index 0000000..9cdfef7 --- /dev/null +++ b/src/shaders/veil.lua @@ -0,0 +1,21 @@ +return love.graphics.newShader[[ + #define fog vec4( 0.85, 0.85, 1.0, 1.0 ) + #define blue vec4( 0.6, 0.6, 0.7, 0.0 ) + + varying float d; +#ifdef VERTEX + uniform mat4 view; + uniform mat4 proj; + vec4 position( mat4 _, vec4 pos ){ + pos.xyz *= 16.0; + vec4 eye = view*pos; + d = clamp( -eye.z / 16.0 - 0.4, 0.0, 1.0 ); + return proj*eye; + } +#endif +#ifdef PIXEL + vec4 effect( vec4 color, Image _, vec2 __, vec2 ___) { + return mix( blue, fog, d); + } +#endif +]] \ No newline at end of file diff --git a/src/tex/cubemap_0.png b/src/tex/cubemap_0.png deleted file mode 100644 index b931a1d..0000000 Binary files a/src/tex/cubemap_0.png and /dev/null differ diff --git a/src/tex/cubemap_1.png b/src/tex/cubemap_1.png deleted file mode 100644 index 30d4bb1..0000000 Binary files a/src/tex/cubemap_1.png and /dev/null differ diff --git a/src/tex/cubemap_2.png b/src/tex/cubemap_2.png deleted file mode 100644 index 78380c5..0000000 Binary files a/src/tex/cubemap_2.png and /dev/null differ diff --git a/src/tex/cubemap_3.png b/src/tex/cubemap_3.png deleted file mode 100644 index 911e0de..0000000 Binary files a/src/tex/cubemap_3.png and /dev/null differ diff --git a/src/tex/cubemap_4.png b/src/tex/cubemap_4.png deleted file mode 100644 index c579eb8..0000000 Binary files a/src/tex/cubemap_4.png and /dev/null differ diff --git a/src/tex/cubemap_5.png b/src/tex/cubemap_5.png deleted file mode 100644 index ad2c5f2..0000000 Binary files a/src/tex/cubemap_5.png and /dev/null differ