Sure, sharing is caring. I'll do a proper release on the forum when my game's more fleshed out. I've included my progress so far, below.
Just added (quad wide) lighting.
Code: Select all
local texw,texh = 0,0
--temp tuples to avoid continous allocation of tables
local shaderp1,shaderp2,shaderp3,shaderp4,shaderp5,shaderp6 = {0,0},{0,0},{0,0},{0,0},{0,0},{0,0}
-- tx,ty is top-left corner of quad on texture, in pixels
-- tw,th is width and height of quad on texture, in pixels
-- flip is horizontal flip of quad on texture, true/false
-- x1,y1..x4,y4 are quad corners on screen in pixels, clockwise starting from top left
-- r,g,b,a are vertex fog colors, in same order
function draw_textured_quad(tx,ty,tw,th,flip, x1,y1, x2,y2, x3,y3, x4,y4, r1,g1,b1,a1, r2,g2,b2,a2, r3,g3,b3,a3, r4,g4,b4,a4)
if flip then
shaderp1[1],shaderp1[2] = (tx+tw)/texw, ty/texh
shaderp2[1],shaderp2[2] = -tw/texw, th/texh
else
shaderp1[1],shaderp1[2] = tx/texw, ty/texh
shaderp2[1],shaderp2[2] = tw/texw, th/texh
end
shaderp3[1],shaderp3[2] = x1, y1
shaderp4[1],shaderp4[2] = x2, y2
shaderp5[1],shaderp5[2] = x3, y3
shaderp6[1],shaderp6[2] = x4, y4
xii_shader:send("p0", shaderp1)
xii_shader:send("rep", shaderp2)
xii_shader:send("v1", shaderp3)
xii_shader:send("v2", shaderp4)
xii_shader:send("v3", shaderp5)
xii_shader:send("v4", shaderp6)
-- I don't know why the vertex color indices are shifted by 1...
quad:setVertex(1, x1,y1, tx/texw,ty/texh, r2,g2,b2,a2)
quad:setVertex(2, x2,y2, (tx+tw)/texw,ty/texh, r3,g3,b3,a3)
quad:setVertex(3, x3,y3, (tx+tw)/texw,(ty+th)/texh, r4,g4,b4,a4)
quad:setVertex(4, x4,y4, tx/texw,(ty+th)/texh, r1,g1,b1,a1)
love.graphics.draw(quad)
end
function set_texture(img)
quad:setTexture(img)
texw,texh = img:getWidth(), img:getHeight()
end
-- what this essentially does is redefines the meaning of the red, green, and blue channels in the texture to any arbitrary colors, plus also the anti-channel (the color you get with RGB 0,0,0, i.e. black).
-- this allows you to do 4-color palette swapping, with gradients! usually palette swap mechanisms replace specific pixel values, which doesn't allow for gradients.
-- colors[4] = {b={R,G,B}, R={R,G,B}, G={R,G,B}, B={R,G,B}}
-- for normal colors, use {{0,0,0}, {1,0,0}, {0,1,0}, {0,0,1}} (i.e. black, red, green, and blue - the default channels of RGB!)
function set_palette(colors)
xii_shader:sendColor("color_0", colors[1])
xii_shader:sendColor("color_r", colors[2])
xii_shader:sendColor("color_g", colors[3])
xii_shader:sendColor("color_b", colors[4])
end
-- alpha channel is intensity. 0 is dark, .5 is fully lit, and 1 is over-lit. so {1,1,1,.5} is normal lighting.
function set_light(color)
xii_shader:sendColor("light", color)
end
quad = love.graphics.newMesh(4, "fan", "stream")
xii_shader = love.graphics.newShader[[
// by xXxMoNkEyMaNxXx and Xii
extern vec2 v1;
extern vec2 v2;
extern vec2 v3;
extern vec2 v4;
extern vec2 p0;
extern vec2 rep;
extern vec3 color_0;
extern vec3 color_r;
extern vec3 color_g;
extern vec3 color_b;
extern vec4 light;
vec2 one=vec2(1.0,1.0);
number c(vec2 v1,vec2 v2)
{
return v1.x*v2.y-v2.x*v1.y;
}
number intersect(vec2 v1,vec2 d1,vec2 v2,vec2 d2)
{
//v1+d1*
return c(v2-v1,d2)/c(d1,d2);
}
vec4 effect(vec4 color, Image img, vec2 UNUSED2, vec2 inverted)
{
vec2 p=vec2(inverted.x,inverted.y);
vec2 A1=normalize(v2-v1);
vec2 A2=normalize(v3-v4);
vec2 B1=normalize(v2-v3);
vec2 B2=normalize(v1-v4);
number Adiv=c(A1,A2);
number Bdiv=c(B1,B2);
vec2 uv;
bvec2 eq0=bvec2(abs(Adiv)<=0.0001,abs(Bdiv)<=0.0001);
if(eq0.x && eq0.y){
//Both edges are parallel, therefore the shape is a parallelogram (Isometric)
number dis=dot(p-v1,A1);
//cos theta
number ct=dot(A1,B1);
//Closest point on v1->A1 to p
vec2 pA=v1+A1*dis;
//uv
number r=length(p-pA)/sqrt(1-ct*ct);
uv=vec2(1-r/length(v2-v3),(dis+r*ct)/length(v2-v1));
}else if(eq0.x){
//One Vanishing point occurs in numerically set scenarios in 3D, and is a feature of 2.5D
//Horizon is A1 (=A2) from B
vec2 Vp=v3+B1*c(v4-v3,B2)/Bdiv;
//Some point in the distance that diagonals go to
vec2 D=Vp+A1*intersect(Vp,A1,v4,normalize(v2-v4));
//uv
number u=intersect(v1,A1,Vp,normalize(p-Vp));
number v=intersect(v1,A1,D,normalize(p-D))-u;
number len=length(v2-v1);
uv=vec2(len-v,u)/len;//Reversed components to match up with other one
}else if(eq0.y){
//If the other edge is the parallel one
vec2 Vp=v1+A1*c(v4-v1,A2)/Adiv;
vec2 D=Vp+B1*intersect(Vp,B1,v4,normalize(v2-v4));
number u=intersect(v3,B1,Vp,normalize(p-Vp));
number len=length(v2-v3);
uv=vec2(u,len-intersect(v3,B1,D,normalize(p-D))+u)/len;
}else{
//Else, two vanishing points
//*intersect(v1,A1,v4,A2)
//*intersect(v3,B1,v4,B2)
//Vanishing points
vec2 A=v1+A1*c(v4-v1,A2)/Adiv;
vec2 B=v3+B1*c(v4-v3,B2)/Bdiv;
//Horizon
vec2 H=normalize(A-B);
//Pixel
uv=vec2(intersect(v4,-H,A,normalize(p-A))/intersect(v4,-H,v2,-A1),intersect(v4,H,B,normalize(p-B))/intersect(v4,H,v2,-B1));
}
vec4 pixel = Texel(img, mod(uv*rep+vec2(p0.x-1,p0.y), one));//This is the current pixel color
// palette swap
vec3 blend_r = mix(color_0, color_r, pixel.r);
vec3 blend_g = mix(color_0, color_g, pixel.g);
vec3 blend_b = mix(color_0, color_b, pixel.b);
vec3 blend = blend_r + blend_g + blend_b;
// light
blend.rgb = light.rgb * light.a * 2.0 * blend.rgb;
// fog
return vec4(mix(blend, color.rgb, color.a), pixel.a);
}
]]