local mat4 = cpml.mat4 local vec3 = cpml.vec3 local cube = { front = {}, top = {}, bottom = {}, left = {}, right = {} } for scale = 1,2 do cube.front[scale] = love.graphics.newMesh( { { "VertexPosition", "float", 3 }, { "VertexTexCoord", "float", 2 }, { "VertexColor", "byte", 4} }, { { 0, 0, 0, 0, 0, 1, 1, 1 }, { 16*scale, 0, 0, 1, 0, 1, 1, 1, }, { 0, 16*scale, 0, 0, 1, 1, 1, 1, }, { 16*scale, 16*scale, 0, 1, 1, 1, 1, 1, }, }, "strip", "static" ) cube.top[scale] = love.graphics.newMesh( { { "VertexPosition", "float", 3 }, { "VertexTexCoord", "float", 2 }, { "VertexColor", "byte", 4} }, { { 0, 0, 0, 0, 0, 1, 1, 1 }, { 16*scale, 0, 0, 1, 0, 1, 1, 1, }, { 0, 0, 16*scale, 0, 1, 1, 1, 1, }, { 16*scale, 0, 16*scale, 1, 1, 1, 1, 1, }, }, "strip", "static" ) cube.bottom[scale] = love.graphics.newMesh( { { "VertexPosition", "float", 3 }, { "VertexTexCoord", "float", 2 }, { "VertexColor", "byte", 4} }, { { 0, 16*scale, 16*scale, 0, 0, 1, 1, 1 }, { 16*scale, 16*scale, 16*scale, 1, 0, 1, 1, 1, }, { 0, 16*scale, 0, 0, 1, 1, 1, 1, }, { 16*scale, 16*scale, 0, 1, 1, 1, 1, 1, }, }, "strip", "static" ) cube.left[scale] = love.graphics.newMesh( { { "VertexPosition", "float", 3 }, { "VertexTexCoord", "float", 2 }, { "VertexColor", "byte", 4} }, { { 0, 0, 0, 0, 0, 1, 1, 1 }, { 0, 16*scale, 0, 1, 0, 1, 1, 1, }, { 0, 0, 16*scale, 0, 1, 1, 1, 1, }, { 0, 16*scale, 16*scale, 1, 1, 1, 1, 1, }, }, "strip", "static" ) cube.right[scale] = love.graphics.newMesh( { { "VertexPosition", "float", 3 }, { "VertexTexCoord", "float", 2 }, { "VertexColor", "byte", 4} }, { { 16*scale, 16*scale, 16*scale, 0, 0, 1, 1, 1 }, { 16*scale, 0, 16*scale, 1, 0, 1, 1, 1, }, { 16*scale, 16*scale, 0, 0, 1, 1, 1, 1, }, { 16*scale, 0, 0, 1, 1, 1, 1, 1, }, }, "strip", "static" ) end local shader_no_discard = { shader = love.graphics.newShader( [[ vec4 effect(vec4 color, Image tex, vec2 texture_coords, vec2 screen_coords) { vec4 texcolor = Texel(tex, texture_coords); return texcolor * color; } ]], [[ uniform mat4 transform; vec4 position(mat4 transform_projection, vec4 vertex_position) { return transform * TransformMatrix * (vertex_position - vec4(vec2(640.0, 480.0) / 2.0, 0.0, 0.0)); } ]] ), width = -1, height = -1, depth_3d = -1 } local shader_discard = { shader = love.graphics.newShader( [[ uniform vec4 rect; vec4 effect(vec4 color, Image tex, vec2 texture_coords, vec2 screen_coords) { if (screen_coords.x < rect.x || screen_coords.x > rect.y || screen_coords.y < rect.z || screen_coords.y > rect.w) discard; vec4 texcolor = Texel(tex, texture_coords); return texcolor * color; } ]], [[ uniform mat4 transform; vec4 position(mat4 transform_projection, vec4 vertex_position) { return transform * TransformMatrix * (vertex_position - vec4(vec2(640.0, 480.0) / 2.0, 0.0, 0.0)); } ]] ), width = -1, height = -1, depth_3d = -1 } local function set_shader_transform(shader, width, height) local depth = (480 / 2) / math.tan(math.rad(config.depth_3d) / 2) local look_at = mat4():look_at(vec3(0, 0, depth), vec3(0, 0, 0), vec3(0, 1, 0)) local perspective = mat4.from_perspective(config.depth_3d, width / height, -0.5, 0.5) local tall = height / 480 > width / 640 if tall then local scale_factor = (480 * width) / (640 * height) shader:send("transform", mat4.scale(mat4.new(), perspective * look_at, vec3(scale_factor))) else shader:send("transform", perspective * look_at) end end return function(R, G, B, A, image, x, y, left, right, top, bottom, big) local scale = big and 2 or 1 if config.depth_3d > 0 then love.graphics.setCanvas{GLOBAL_CANVAS, depth = true} love.graphics.push() love.graphics.origin() love.graphics.setDepthMode("lequal", true) local shader local current_width = love.graphics.getWidth() local current_height = love.graphics.getHeight() if left and right and top and bottom then love.graphics.setShader(shader_discard.shader) local scale_factor = math.min(current_width / 640, current_height / 480) local rect_left = (current_width - scale_factor * 640) / 2 + left * scale_factor local rect_right = (current_width - scale_factor * 640) / 2 + right * scale_factor local rect_top = (current_height - scale_factor * 480) / 2 + top * scale_factor local rect_bottom = (current_height - scale_factor * 480) / 2 + bottom * scale_factor shader_discard.shader:send("rect", {rect_left, rect_right, rect_top, rect_bottom}) shader = shader_discard else love.graphics.setShader(shader_no_discard.shader) shader = shader_no_discard end if current_width ~= shader.width or current_height ~= shader.height or config.depth_3d ~= shader.depth_3d then set_shader_transform(shader.shader, current_width, current_height) shader.width = current_width shader.height = current_height shader.depth_3d = config.depth_3d end if A ~= 1 or y > 480 / 2 then love.graphics.setColor(R, G, B, A) cube.top[scale]:setTexture(image) love.graphics.draw(cube.top[scale], x, y) end love.graphics.setColor(R / 2, G / 2, B / 2, A) if A ~= 1 or y < 480 / 2 then cube.bottom[scale]:setTexture(image) love.graphics.draw(cube.bottom[scale], x, y) end if A ~= 1 or x > 640 / 2 then cube.left[scale]:setTexture(image) love.graphics.draw(cube.left[scale], x, y) end if A ~= 1 or x < 640 / 2 then cube.right[scale]:setTexture(image) love.graphics.draw(cube.right[scale], x, y) end love.graphics.setColor(R, G, B, A) cube.front[scale]:setTexture(image) love.graphics.draw(cube.front[scale], x, y) love.graphics.setShader() love.graphics.setDepthMode() love.graphics.pop() love.graphics.setCanvas(GLOBAL_CANVAS) else love.graphics.setColor(R, G, B, A) love.graphics.draw(image, x, y, 0, scale, scale) end end