From ecd29fba147741f7f709fff7b1c54174bad0521b Mon Sep 17 00:00:00 2001 From: connershoop <31523466+connershoop@users.noreply.github.com> Date: Wed, 19 Nov 2025 19:43:37 +0000 Subject: [PATCH 1/4] add new shader to rotate normal map vectors to the rotation of the sprite being drawn --- lib/body.lua | 6 ++++++ lib/shaders/normal_rotate.glsl | 22 ++++++++++++++++++++++ 2 files changed, 28 insertions(+) create mode 100644 lib/shaders/normal_rotate.glsl diff --git a/lib/body.lua b/lib/body.lua index 9ef0064..aaba81b 100644 --- a/lib/body.lua +++ b/lib/body.lua @@ -575,11 +575,17 @@ end function body:drawNormal() if not self.refraction and not self.reflection and self.normalMesh then love.graphics.setColor(1, 1, 1) + + love.graphics.setShader(body.normalRotateShader) + body.normalRotateShader:send("rotation", self.rotation) + if self.type == 'animation' then self.animation:draw(self.normal, self.x, self.y, self.rotation, self.scalex, self.scaley, self.nx, self.ny) else love.graphics.draw(self.normalMesh, self.x, self.y, self.rotation, self.scalex, self.scaley, self.nx, self.ny) end + + love.graphics.setShader() end end diff --git a/lib/shaders/normal_rotate.glsl b/lib/shaders/normal_rotate.glsl new file mode 100644 index 0000000..e91edad --- /dev/null +++ b/lib/shaders/normal_rotate.glsl @@ -0,0 +1,22 @@ +extern float rotation; + +vec4 effect(vec4 color, Image normalTex, vec2 uv, vec2 pixel_coords) { + vec4 tex = Texel(normalTex, uv); + + vec3 normal = tex.rgb * 2.0 - 1.0; + + // Z-axis rotation (rotates in XY plane) + float c = cos(rotation); + float s = sin(rotation); + vec3 rotated = vec3( + c * normal.x - s * normal.y, // X' + s * normal.x + c * normal.y, // Y' + normal.z // Z' + ); + + rotated = normalize(rotated); + + vec3 encoded = rotated * 0.5 + 0.5; + + return vec4(encoded, tex.a); +} \ No newline at end of file From f73b364ce729e38e6fa43616a2d78e9183e5fdcb Mon Sep 17 00:00:00 2001 From: connershoop <31523466+connershoop@users.noreply.github.com> Date: Wed, 19 Nov 2025 19:46:08 +0000 Subject: [PATCH 2/4] add contrib --- README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/README.md b/README.md index 1a026c1..00e6ca0 100644 --- a/README.md +++ b/README.md @@ -53,3 +53,4 @@ end - @Buckle2000 - Benoit Giannangeli @giann - Ivory @tiwe0 +- Conner @connershoop From e1a8f3bd6813da4a0dffb480cef229821cd2d381 Mon Sep 17 00:00:00 2001 From: connershoop <31523466+connershoop@users.noreply.github.com> Date: Fri, 21 Nov 2025 16:37:45 +0000 Subject: [PATCH 3/4] add import for normal rotate shader --- lib/body.lua | 1 + 1 file changed, 1 insertion(+) diff --git a/lib/body.lua b/lib/body.lua index aaba81b..f881607 100644 --- a/lib/body.lua +++ b/lib/body.lua @@ -9,6 +9,7 @@ body.__index = body body.glowShader = love.graphics.newShader(_PACKAGE.."/shaders/glow.glsl") body.materialShader = love.graphics.newShader(_PACKAGE.."/shaders/material.glsl") +body.normalRotateShader = love.graphics.newShader(_PACKAGE .. "/shaders/normal_rotate.glsl") local function new(id, type, ...) local args = {...} From e1d853160879be2b3261b2fc02eb5a80da763146 Mon Sep 17 00:00:00 2001 From: connershoop Date: Wed, 24 Dec 2025 06:43:37 -0700 Subject: [PATCH 4/4] add normal map rotation to normal map example --- examples/normalMap.lua | 30 ++++++++++++++++++++++++------ 1 file changed, 24 insertions(+), 6 deletions(-) diff --git a/examples/normalMap.lua b/examples/normalMap.lua index f80e2f3..f493630 100644 --- a/examples/normalMap.lua +++ b/examples/normalMap.lua @@ -1,34 +1,52 @@ -- Example: Normal map Example local LightWorld = require "lib" local image, image_normal -local lightWorld, lightMouse +local lightWorld, lightMouse, imageBody, font +local rotation = 0 local function load() -- load images image = love.graphics.newImage("examples/img/normalMap/rock.png") image_normal = love.graphics.newImage("examples/img/normalMap/normal.png") + -- load font + font = love.graphics.newImageFont("examples/img/complex/font.png", " abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789.,!?-+/():;%&`'*#=[]\"") + love.graphics.setFont(font) -- create light world lightWorld = LightWorld({ambient = {0.21,0.21,0.21}}) -- create light lightMouse = lightWorld:newLight(0, 0, 160, 160, 160, 300) - lightMouse.normalInvert = true + lightMouse.normalInvert = true -- create shadow bodys - local w, h = love.graphics.getWidth(), love.graphics.getHeight() - lightWorld:newImage(image, w/2, h/2):setNormalMap(image_normal) + local w, h = love.graphics.getWidth(), love.graphics.getHeight() + imageBody = lightWorld:newImage(image, w/2, h/2) + imageBody:setNormalMap(image_normal) end local function update(dt) love.window.setTitle("Light vs. Shadow Engine (FPS:" .. love.timer.getFPS() .. ")") - lightWorld:update(dt) + lightWorld:update(dt) lightMouse:setPosition(love.mouse.getX(), love.mouse.getY()) + + -- Handle arrow key rotation + if love.keyboard.isDown("left") then + rotation = rotation - 2 * dt + end + if love.keyboard.isDown("right") then + rotation = rotation + 2 * dt + end + imageBody:setRotation(rotation) end local function draw() love.graphics.clear(0.21,0.21,0.21) lightWorld:draw(function(l, t, w, h, s) love.graphics.setColor(1, 1, 1) - love.graphics.draw(image, w/2-(image:getWidth()/2), h/2-(image:getHeight()/2)) + love.graphics.rectangle("fill", 0, 0, love.graphics.getWidth(), love.graphics.getHeight()) + love.graphics.draw(image, w/2, h/2, rotation, 1, 1, image:getWidth()/2, image:getHeight()/2) end) + love.graphics.setBlendMode("alpha") + love.graphics.setColor(0, 0.5, 1) + love.graphics.print("Arrow Keys: Rotate Object", 4, love.graphics.getHeight() - 20 * 1) end return {