<p>I am trying to port the Bruneton Ocean demo to Vulkan and I am having a bit of trouble with the coordinate system. I am using the matrices from the original code but I am not sure what this is doing:</p>
<pre class="lang-c prettyprint-override"><code>mat4s view = mat4s{
    0.0, -1.0, 0.0, 0.0,
    0.0, 0.0, 1.0, -ch,
    -1.0, 0.0, 0.0, 0.0,
    0.0, 0.0, 0.0, 1.0
};
</code></pre>
<p><code>ch</code> is the camera height. From what I understand the water surface geometry is 2D (screen space) and we are trying to project it to 3D. I also think it's using an xy plane and z for height.</p>
<p>The projection matrix is standard. I verified that the screen space coordinate lie within [-1,1]. If I render the screen quads un-modified they cover the screen correctly.</p>
<p>Omitting the animation code, here's how it's used in the vertex shader:</p>
<pre><code>vec3 cameraDir = normalize((screenToCamera * gl_Vertex).xyz);
vec3 worldDir = (cameraToWorld * vec4(cameraDir, 0.0)).xyz;
float t = (heightOffset - worldCamera.z) / worldDir.z;

vec2 u = worldToWind * (worldCamera.xy + t * worldDir.xy);
vec3 dPdu = vec3(1.0, 0.0, 0.0);
vec3 dPdv = vec3(0.0, 1.0, 0.0);
vec2 sigmaSq = sigmaSqTotal;

float lod = - t / worldDir.z * lods.y; // size in meters of one grid cell, projected on the sea surface

vec3 dP = vec3(0.0, 0.0, heightOffset);

// wave animation

vec3 P = vec3(windToWorld * (u + dP.xy), dP.z);

if (t &gt; 0.0) {
    gl_Position = worldToScreen * vec4(P, 1.0);
}
</code></pre>
<p><code>cameraToWorld</code> is the inverse of the <code>view</code> matrix I posted above. I am thinking it's a view matrix issue because I would expect <code>t</code> to be always positive, given my camera position (which is fixed at [0, 2, 0]) and wave height (here called <code>heightOffset</code>).</p>
<p>Instead, it's negative for the left half of the screen (the black quads fail the <code>t &gt; 0</code> test and are left unprojected):
<a href="https://i.sstatic.net/cbG1AOgY.png" rel="nofollow noreferrer"><img src="https://i.sstatic.net/cbG1AOgY.png" alt="enter image description here" /></a></p>
<p>I know that Vulkan has a top-left origin compared to OpenGL, but not sure this plays a role here.</p>

CC BY-SA 4.0
2024-07-01T13:32:57.830Z
The view matrix is basically rearranging the x,y,z components of the vertex. In this case the x maps to -y, y maps to -z, and z  maps to -x. So x,y,z becomes -y,-z, x. It also translates the y component by -ch.
pmw1234
CC BY-SA 4.0
2024-07-04T07:48:16.290Z
Thanks! I figured it was some find of re-arrangement but couldn't figure out why it wasn't working. Turns out the original code was storing the matrix in row major while my code was storing it column major. Translating the matrix fixed the issue.
Marco Castorina
<projections><vulkan>
Ocean screen grid projection and animation
Marco Castorina
# Ocean screen grid projection and animation

(Asked by: username_0 on 2024-06-30)

I am trying to port the Bruneton Ocean demo to Vulkan and I am having a bit of trouble with the coordinate system. I am using the matrices from the original code but I am not sure what this is doing:

```c
mat4s view = mat4s{
    0.0, -1.0, 0.0, 0.0,
    0.0, 0.0, 1.0, -ch,
    -1.0, 0.0, 0.0, 0.0,
    0.0, 0.0, 0.0, 1.0
};

```

`ch` is the camera height. From what I understand the water surface geometry is 2D (screen space) and we are trying to project it to 3D. I also think it's using an xy plane and z for height.

The projection matrix is standard. I verified that the screen space coordinate lie within [-1,1]. If I render the screen quads un-modified they cover the screen correctly.

Omitting the animation code, here's how it's used in the vertex shader:

```
vec3 cameraDir = normalize((screenToCamera * gl_Vertex).xyz);
vec3 worldDir = (cameraToWorld * vec4(cameraDir, 0.0)).xyz;
float t = (heightOffset - worldCamera.z) / worldDir.z;

vec2 u = worldToWind * (worldCamera.xy + t * worldDir.xy);
vec3 dPdu = vec3(1.0, 0.0, 0.0);
vec3 dPdv = vec3(0.0, 1.0, 0.0);
vec2 sigmaSq = sigmaSqTotal;

float lod = - t / worldDir.z * lods.y; // size in meters of one grid cell, projected on the sea surface

vec3 dP = vec3(0.0, 0.0, heightOffset);

// wave animation

vec3 P = vec3(windToWorld * (u + dP.xy), dP.z);

if (t > 0.0) {
    gl_Position = worldToScreen * vec4(P, 1.0);
}

```

`cameraToWorld` is the inverse of the `view` matrix I posted above. I am thinking it's a view matrix issue because I would expect `t` to be always positive, given my camera position (which is fixed at [0, 2, 0]) and wave height (here called `heightOffset`).

Instead, it's negative for the left half of the screen (the black quads fail the `t > 0` test and are left unprojected):
[![enter image description here](https://i.sstatic.net/cbG1AOgY.png)](https://i.sstatic.net/cbG1AOgY.png)

I know that Vulkan has a top-left origin compared to OpenGL, but not sure this plays a role here.

**Tags:** projections, vulkan

> **Comments:**
> **username_1**: The view matrix is basically rearranging the x,y,z components of the vertex. In this case the x maps to -y, y maps to -z, and z  maps to -x. So x,y,z becomes -y,-z, x. It also translates the y component by -ch.  
> **username_0**: Thanks! I figured it was some find of re-arrangement but couldn't figure out why it wasn't working. Turns out the original code was storing the matrix in row major while my code was storing it column major. Translating the matrix fixed the issue.  

---

## 0 answers

