..About damn time :)

by baggers

Oh progress feels so good!

Ok, now given some code like this:

(defun-g vert ((vert pos-col) &uniform (s space-g) (w space-g))
  (in s
    (in w
      (p! (v! 1 1 1 1)))
  (values (v! (pos vert) 1.0)
          (col vert)))

The in portion does nothing useful, it purly exists so that there is a position (the p!) which is created inside the scope of the space w. That position is returned into the scope of space s. To ensure this is valid the compile needs to multiple the position by some kind of w space to s space matrix.

Lets look at the compile output (it's been cleaned up for readability)

#version 330

layout(location = 0) in vec3 fk_vert_position;
layout(location = 1) in vec4 fk_vert_color;

out vec4 OUT_34V;
uniform mat4 W-TO-S;

void main() {
  (W-TO-S * vec4(1,1,1,1));
  gl_Position = vec4(fk_vert_position,1.0f);
  OUT_34V = fk_vert_color;

Here we can see that there is no mention of w, s, positions or spaces. The compiler has created a uniform to hold the w space to s space transform and multiplied it with the vec4.

On the cpu side we can find this code

(let ((w-to-s (spaces:get-transform w s)))
  (when w-to-s
     (when (>= w-to-s-uniform-location 0)
       (cepl-gl::uniform-matrix-4ft w-to-s-uniform-location w-to-s))))

Here we see that the original spaces w & s are passed to the get-transform function which returns the matrix4 which is uploaded.

As you would imagine there are still plenty of little bugs to clean up, but those feel like nothing compared to how much work this has taken. I'm pretty stoked right now.

I'm looking forward to posting a proper example of how you would use this in regular shaders soon.

That's enough for this week


Last Edited on Sun Jan 03 2016 11:55:28 GMT-0500 (EST)

ferris commented

Dude this is SO cool to see! The in scopes are super readable and easy to understand, and the compiler-generated code is as minimal as it should be. Can't wait to see some side-by-sides of code with and without this feature next week ;D

on Sun Jan 03 2016 12:33:12 GMT-0500 (EST)

bau5 commented

Sorry I don't know anything about this project, what's the goal with this??

on Sun Jan 03 2016 13:38:42 GMT-0500 (EST)

baggers commented

@Bau5: (Im assuming no graphics knowledge so sorry if this is too basic and let me know if you want the gritty :) ) In shaders we do a lot of different calculations from different things 'point of view', so we want to draw our world from the camera's point of view, we can calculate shadows as whatever can't be seen from a lights 'point of view' etc.

From now on we will refer to this 'point of view' as a space (vector space to be precise)

We also want to transform points between different spaces. The way of transforming from one space to another is described by a matrix. Now glsl lets us work with vectors (which we will use for points) and matrices. But what is weird is that when we are discussing the problem we are talking about spaces, yet when we have to implement it we have to work with matrices. This feels a little uncomfortable as we have to maintain the mapping in our head, we have to know what spaces we are moving things between. Worse, if you are reading someone else's code then unless they have very good variable names, it's gonna be hard to work out the context they had in their heads.

It's this kind of stuff that makes graphics programming more confusing (at least to me). So the obvious thing to do is to add some way of talking about spaces in code, and if we are doing that, then we should make the compiler check to see if what we are saying is sane. So like we have type checking we could have space checking.

You may rightly wonder why we would want this. Lets say we want to work out what is being reflected off some mirror in a game. We have information about where things are position in the game world, but we actually want these details from the point of view of in camera in game.

By using the in syntax I've added to my compiler I am saying that everything inside that scope is in (for example) camera space. Then, if you use any position defined in world space (like the mirrors position in the example above) then the compiler can detect this and covert the position to the correct space for you. Guaranteeing your positions are in the right space.

Also now that the spaces are being talked about explicitly it should be easier to read other people's code.

That's the idea really, this all came out of me trying to learn about shader programming from looking at shader toy and getting really annoyed as I couldnt figure out the reasoning for what people were doing, after chatting with jake I understood that it wasnt just that I didnt know enough but it was also that this is quite tricky anyway. This is my first attempt at adding something that seeks to address this stuff.

The hardest bit is that shaders need to be fast, so I cant waste performance just because I want cleaner code, so I needed to be sure the compiler could turn all the spaces and positions into the correct matrices and vectors so that the gpu doesnt have to deal with this at runtime. It's been a struggle :)

p.s. Im sure the 'points of view' analogy would be torn apart by any proper graphics programmer, but I think it gets the idea across.

on Mon Jan 04 2016 13:59:25 GMT-0500 (EST)

- Last Edited on Mon Jan 04 2016 14:05:35 GMT-0500 (EST)

bau5 commented

nice makes total since, thanks for the explanation +1

on Mon Jan 04 2016 18:46:11 GMT-0500 (EST)

Zach Harvest commented

@baggers What an awesome write up! I would edit it into your post!

on Tue Jan 05 2016 13:24:01 GMT-0500 (EST)