cambridge/tetris/components/draw_block.lua

301 lines
6.1 KiB
Lua
Raw Normal View History

2022-07-04 23:05:40 -05:00
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