Strange cpml and vertex shader issue

Questions about the LÖVE API, installing LÖVE and other support related questions go here.
Forum rules
Before you make a thread asking for help, read this.
Post Reply
Keen
Prole
Posts: 2
Joined: Sun Oct 07, 2018 5:42 am

Strange cpml and vertex shader issue

Post by Keen »

I'm not sure if this is a problem with cpml, or something weird with the rendering context internally in love2d, but I'm seeing a strange issue causing rendered geometry to disappear when using a model view matrix where the camera has a forward vector that points predominantly in the +X or -X direction, in otherwords 45 degrees off from an identity matrix.

I attached an example showing a view point rotating back and fourth and the geometry disappearing when the angle surpasses -45 or +45 degrees. Used with love-11.1.0-win64
matrixproblem.love
(54.14 KiB) Downloaded 187 times

Heres the source of the example:

Code: Select all

cpml = require "libraries/cpml"
color = cpml.color
mat4 = cpml.mat4
quat = cpml.quat
vec2 = cpml.vec2
vec3 = cpml.vec3
bound2 = cpml.bound2
bound3 = cpml.bound3
vec2.one = vec2(1, 1)
vec3.one = vec3(1, 1, 1)

local vertexShader= [[
extern mat4 modelViewMatrix;
extern mat4 projectionMatrix;
vec4 position(mat4 notUsedMatrix, vec4 vertexPosition)
{
	vec4 vertex = projectionMatrix*modelViewMatrix*vertexPosition;
	return vertex;
}
]]

local pixelShader = [[
vec4 effect(vec4 vertexColor, Image texture, vec2 textureCoords, vec2 screenCoords)
{
	vec4 color = Texel(texture, textureCoords);
	return color*vertexColor;
}
]]

local shader = love.graphics.newShader(pixelShader, vertexShader)

local vertexFormat = {
	{"VertexPosition", "float", 3},
	{"VertexTexCoord", "float", 2},
	{"VertexColor", "byte", 4},
}

local vertexData = {
	{
		-0.5, 0, 0,
		0, 0,
		1, 0, 0, 1
	},
	{
		0.5, 0, 0,
		1, 0,
		0, 1, 0, 1
	},
	{
		0, 1, 0,
		1, 1,
		0, 0, 1, 1
	}
}

local mesh = love.graphics.newMesh(vertexFormat, vertexData, "triangles", "dynamic")

function love.draw()
	local yaw = math.cos(love.timer.getTime())*1
	love.graphics.print("degrees "..math.floor(math.deg(yaw)), 10, 10)
	local cameraMatrix = mat4():identity()
	cameraMatrix:translate(cameraMatrix, vec3(0, 0, 4))
	cameraMatrix:rotate(cameraMatrix, yaw, vec3.unit_y)
	cameraMatrix = mat4.invert(cameraMatrix, cameraMatrix)

	local projectionMatrix = mat4.from_perspective(70, 1.7777, 0.01, 1000)

	shader:send("modelViewMatrix", "column", cameraMatrix)
	shader:send("projectionMatrix", "column", projectionMatrix)

	love.graphics.setShader(shader)
	
	love.graphics.draw(mesh, 0, 0)

	love.graphics.setShader()
end
User avatar
pgimeno
Party member
Posts: 3656
Joined: Sun Oct 18, 2015 2:58 pm

Re: Strange cpml and vertex shader issue

Post by pgimeno »

Hi, welcome to the forums.

I haven't dug into the why, but this corrected it for me:

Code: Select all

Replace:
	cameraMatrix:translate(cameraMatrix, vec3(0, 0, 4))
	cameraMatrix:rotate(cameraMatrix, yaw, vec3.unit_y)
	cameraMatrix = mat4.invert(cameraMatrix, cameraMatrix)
with:
	cameraMatrix:rotate(cameraMatrix, -yaw, vec3.unit_y)
	cameraMatrix:translate(cameraMatrix, vec3(0, 0, -4))
It might be the matrix inversion code in cpml, not sure.

Edit: Yeah, replacing the invert call with my matrix inversion code makes it work fine.

Edit2: Here's my matrix inversion code:

Code: Select all

-- Matrices are in row-major order

local function det_mat4(a)
  return a[1] * ( a[10] * (a[15]*a[ 8] - a[16]*a[ 7])
                + a[11] * (a[16]*a[ 6] - a[14]*a[ 8])
                + a[12] * (a[14]*a[ 7] - a[15]*a[ 6]))
       + a[2] * ( a[11] * (a[13]*a[ 8] - a[16]*a[ 5])
                + a[12] * (a[15]*a[ 5] - a[13]*a[ 7])
                + a[ 9] * (a[16]*a[ 7] - a[15]*a[ 8]))
       + a[3] * ( a[10] * (a[16]*a[ 5] - a[13]*a[ 8])
                + a[12] * (a[13]*a[ 6] - a[14]*a[ 5])
                + a[ 9] * (a[14]*a[ 8] - a[16]*a[ 6]))
       + a[4] * ( a[10] * (a[13]*a[ 7] - a[15]*a[ 5])
                + a[11] * (a[14]*a[ 5] - a[13]*a[ 6])
                + a[ 9] * (a[15]*a[ 6] - a[14]*a[ 7]))
end

local function invert_mat4(b, a)
  local det = det_mat4(a)
  if det ~= 0 then
    b[ 1], b[ 2], b[ 3], b[ 4],
    b[ 5], b[ 6], b[ 7], b[ 8],
    b[ 9], b[10], b[11], b[12],
    b[13], b[14], b[15], b[16]
      = ( a[10] * (a[15]*a[ 8] - a[16]*a[ 7])
        + a[11] * (a[16]*a[ 6] - a[14]*a[ 8])
        + a[12] * (a[14]*a[ 7] - a[15]*a[ 6])) / det
      , ( a[10] * (a[16]*a[ 3] - a[15]*a[ 4])
        + a[11] * (a[14]*a[ 4] - a[16]*a[ 2])
        + a[12] * (a[15]*a[ 2] - a[14]*a[ 3])) / det
      , ( a[14] * (a[ 3]*a[ 8] - a[ 4]*a[ 7])
        + a[15] * (a[ 4]*a[ 6] - a[ 2]*a[ 8])
        + a[16] * (a[ 2]*a[ 7] - a[ 3]*a[ 6])) / det
      , ( a[10] * (a[ 4]*a[ 7] - a[ 3]*a[ 8])
        + a[11] * (a[ 2]*a[ 8] - a[ 4]*a[ 6])
        + a[12] * (a[ 3]*a[ 6] - a[ 2]*a[ 7])) / det
      , ( a[11] * (a[13]*a[ 8] - a[16]*a[ 5])
        + a[12] * (a[15]*a[ 5] - a[13]*a[ 7])
        + a[ 9] * (a[16]*a[ 7] - a[15]*a[ 8])) / det
      , ( a[ 1] * (a[11]*a[16] - a[12]*a[15])
        + a[13] * (a[12]*a[ 3] - a[11]*a[ 4])
        + a[ 9] * (a[15]*a[ 4] - a[16]*a[ 3])) / det
      , ( a[ 1] * (a[15]*a[ 8] - a[16]*a[ 7])
        + a[13] * (a[ 4]*a[ 7] - a[ 3]*a[ 8])
        + a[ 5] * (a[16]*a[ 3] - a[15]*a[ 4])) / det
      , ( a[ 1] * (a[12]*a[ 7] - a[11]*a[ 8])
        + a[ 5] * (a[11]*a[ 4] - a[12]*a[ 3])
        + a[ 9] * (a[ 3]*a[ 8] - a[ 4]*a[ 7])) / det
      , ( a[10] * (a[16]*a[ 5] - a[13]*a[ 8])
        + a[12] * (a[13]*a[ 6] - a[14]*a[ 5])
        + a[ 9] * (a[14]*a[ 8] - a[16]*a[ 6])) / det
      , ( a[ 1] * (a[12]*a[14] - a[10]*a[16])
        + a[13] * (a[10]*a[ 4] - a[12]*a[ 2])
        + a[ 9] * (a[16]*a[ 2] - a[14]*a[ 4])) / det
      , ( a[ 1] * (a[16]*a[ 6] - a[14]*a[ 8])
        + a[13] * (a[ 2]*a[ 8] - a[ 4]*a[ 6])
        + a[ 5] * (a[14]*a[ 4] - a[16]*a[ 2])) / det
      , ( a[ 1] * (a[10]*a[ 8] - a[12]*a[ 6])
        + a[ 5] * (a[12]*a[ 2] - a[10]*a[ 4])
        + a[ 9] * (a[ 4]*a[ 6] - a[ 2]*a[ 8])) / det
      , ( a[10] * (a[13]*a[ 7] - a[15]*a[ 5])
        + a[11] * (a[14]*a[ 5] - a[13]*a[ 6])
        + a[ 9] * (a[15]*a[ 6] - a[14]*a[ 7])) / det
      , ( a[ 1] * (a[10]*a[15] - a[11]*a[14])
        + a[13] * (a[11]*a[ 2] - a[10]*a[ 3])
        + a[ 9] * (a[14]*a[ 3] - a[15]*a[ 2])) / det
      , ( a[ 1] * (a[14]*a[ 7] - a[15]*a[ 6])
        + a[13] * (a[ 3]*a[ 6] - a[ 2]*a[ 7])
        + a[ 5] * (a[15]*a[ 2] - a[14]*a[ 3])) / det
      , ( a[ 1] * (a[11]*a[ 6] - a[10]*a[ 7])
        + a[ 5] * (a[10]*a[ 3] - a[11]*a[ 2])
        + a[ 9] * (a[ 2]*a[ 7] - a[ 3]*a[ 6])) / det
  end
  return det
end
Keen
Prole
Posts: 2
Joined: Sun Oct 07, 2018 5:42 am

Re: Strange cpml and vertex shader issue

Post by Keen »

Thanks. I came to the same conclusion that its something in cpml, or at least the way I was using it, although I didn't track it down to the invert call.

I started implementing vector/matrix library based on Brinevector3D and matrix function implementation from cpml and as soon as I had the APIs that the example required and replaced them it worked.

The funny thing is my matrix invert function is pretty much identical to cpml which makes me think I was using the library incorrectly or something.
User avatar
pgimeno
Party member
Posts: 3656
Joined: Sun Oct 18, 2015 2:58 pm

Re: Strange cpml and vertex shader issue

Post by pgimeno »

Checked it now. The problem is that CPML's code isn't prepared to deal with inversion in place. When a = out, the determinant is calculated from the already overwritten values of a[1] through a[4].

Test case:

Code: Select all

local cpml = require 'libraries.cpml.init'

local a = cpml.mat4()
for i = 2, 5 do a[i] = i end
local b = cpml.mat4(a)
b:invert(b)
print(a * b) -- output: [ -0.818, +0.000, +0.000, +0.000, +0.000, -0.818, +0.000, +0.000, +0.000, +0.000, -0.818, +0.000, +0.000, +0.000, +0.000, -0.818 ]
Post Reply

Who is online

Users browsing this forum: Bing [Bot] and 3 guests