-
Notifications
You must be signed in to change notification settings - Fork 248
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Sketch simple shaders #14
Conversation
fn degamma(v: Vec4) -> Vec4 { | ||
decode_srgb(v.xyz).extend(v.w) | ||
} | ||
|
||
fn hsv_to_rgb(c: Vec3) -> Vec3 { | ||
let K = Vec4::new(1.0, 2.0 / 3.0, 1.0 / 3.0, 3.0); | ||
let p = ((c.xxx + K.xyz).fract() * 6.0 - K.www).abs(); | ||
c.z * lerp(K.xxx, (p - K.xxx).clamp(0.0, 1.0), c.y) | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Looks like I copy 'n pasted swizzles inhere. Can remove.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Looks like glam-rs
will need Add<f32>
and Sub<f32>
implemented for it's vector types.
@@ -0,0 +1,131 @@ | |||
use lighting; | |||
|
|||
bitflags! { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Would be quite nice to use this.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
can also try https://crates.io/crates/enumflags2, I find it even more ergonomic but it is a proc-macro instead so slower to build
world_pos: Vec3, | ||
opacity: Vec3, | ||
|
||
#[flat] |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Not sure what kind of shape these attributes will end up taking, but this is an example.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Alternative syntax: #[spriv_attr(flat)]
or something like this.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
as this is fragment shader input/layout it would likely have some attribute on the struct as as well including that name, so then this flat keyword ideally share namespace / part of the naming here also to make it explicit.
not too common to use though, but need to be supported
constants: Constants, | ||
inputs: Inputs, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Probably should talk about bindings in a new issue / PR.
env_params: lighting::EnvParams, | ||
view_params: lighting::ViewParams, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Would be nice to just use our own types here instead of what the GLSL thing does (raw vec4's).
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
yup for sure, will be interesting what repr
we will end up on the structs with, and if this top level struct has a repr here, can it also enforce (I hope so) that all the structs and types inside it also has it
lighting::ark_light(surface_params, constants.view_params, constants.env_params).extend(input.opacity) | ||
} else { | ||
(input.diffuse_color.truncate() * input.diffuse_color.w()).extend(input.opacity) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
These .extend
and .truncate
calls are kind of fine, but they do get tiresome after a while.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
it is rather cryptic of what does it even mean to truncate a diffuse color? may be other options than having an rgba color stored in a Vec4 with the glam naming here. the GLSL/HLSL swizzles and alias of rgba/xyzw is nice and more familar (just as the original code was diffuse_color.rgb
which is very clear).
Could simply have diffuse_color.xyz()
function in the math library instead of truncate here
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
don't look the wording of .extend()
either, also cryptic
let scale = extract_conservative_scale_from_transform(object_to_world); | ||
object_to_world = Mat4::from_mat3( | ||
if spirv::view_index() == 0 { | ||
global_uniforms.view_to_world.to_mat3() |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I invented glam-rs
functions to_mat3
and from_mat3
here.
if instance.flags.contains(ALPHA_BLENDING_ENABLE | PREMULTIPLIED_ALPHA_ENABLE) { | ||
if instance.flags.contains(PREMULTIPLIED_ALPHA_ENABLE) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Somehow complex match
patterns on bitflags!
isn't ideal.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
think this is pretty fine though, somewhat cleaner and less error prone to read than the GLSL switch statement with bitwise logic in it me thinks.
and for other cases Rust's match
will be really good
diffuse_color.a = 1.0; | ||
} | ||
|
||
let position = if spirv::view_index() == 0 { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I figured we could have a bunch of these builtins in core::arch::spirv
similar to how _mm_set_p1
for example lives in core::arch::x86_64
|
||
position.set_y(-position.y()) | ||
|
||
position |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The GLSL function sets more interpolators then just position; we should find a way of setting this reliably between shader stages so that we can safely match then up. Potentially without all regular shader language magic around these.
From @h3r2tic
|
|
||
#[vertex_shader] | ||
fn main() -> Vec4 { | ||
let instance = instance_data[spirv::instance_index()]; // gl_InstanceIndex |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
spirv::instance_index
looks a bit weird -- as in, the namespace sounds weird. I would expect the instance_index
to be in some draw context, not in a namespace related to the instruction set. It's almost as if having x86_64::current_thread
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
agreed. probably should be a decorated parameter to the main function that you declare that you want to have the instance index. GLSL is not a good base here with loose globals, prefer the explicit inputs & outputs of HLSL and think that would fit better in explicit Rust land also
let hsv = rgb_to_hsv(rgb); | ||
|
||
let hsv = Vec3::new( | ||
(hsv.x() + instance.hsv_transform_data.x()).fract(), |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The .x()
etc could probably become just .x
. I believe glam
uses methods since internally it uses SIMD types that we don't need on the GPU. With different vector types we can have just .x
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
good point, that would be nice
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Not needing SIMD types isn't entirely true, unfortunately - NVIDIA still has massive performance losses when they non-SIMD types are used for loads and stores instead of the SIMD types.
Now, if we want that to impact our std-lib design is another question, because a load-store-vectorizer optimization pass can take care of that just as well.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Not needing SIMD types isn't entirely true, unfortunately - NVIDIA still has massive performance losses when they non-SIMD types are used for loads and stores instead of the SIMD types
It is also possible to just map types to spir-v types. I have been doing that in rlsl, although reusing rusts simd types probably makes more sense.
It looks like this
#[spirv(Vec4)]
#[repr(C)]
#[derive(Debug, Clone, Copy, PartialEq)]
pub struct Vec4<T> {
pub x: T,
pub y: T,
pub z: T,
pub w: T,
}
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
although reusing rusts simd types probably makes more sense.
Looked up the tracking issue for #[repr(simd)]
, looks like it's quite intense. Anyway, I believe the current WIP would automatically compile it to a spir-v SIMD type, I'm guessing it shows up as an Abi::Vector
which just straight dumps to a spir-v vector (probably want to deopt in a couple cases that aren't supported eventually, but anyway, first draft)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Nice work!
@@ -0,0 +1,131 @@ | |||
use lighting; | |||
|
|||
bitflags! { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
can also try https://crates.io/crates/enumflags2, I find it even more ergonomic but it is a proc-macro instead so slower to build
env_params: lighting::EnvParams, | ||
view_params: lighting::ViewParams, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
yup for sure, will be interesting what repr
we will end up on the structs with, and if this top level struct has a repr here, can it also enforce (I hope so) that all the structs and types inside it also has it
world_pos: Vec3, | ||
opacity: Vec3, | ||
|
||
#[flat] |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
as this is fragment shader input/layout it would likely have some attribute on the struct as as well including that name, so then this flat keyword ideally share namespace / part of the naming here also to make it explicit.
not too common to use though, but need to be supported
lighting::ark_light(surface_params, constants.view_params, constants.env_params).extend(input.opacity) | ||
} else { | ||
(input.diffuse_color.truncate() * input.diffuse_color.w()).extend(input.opacity) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
it is rather cryptic of what does it even mean to truncate a diffuse color? may be other options than having an rgba color stored in a Vec4 with the glam naming here. the GLSL/HLSL swizzles and alias of rgba/xyzw is nice and more familar (just as the original code was diffuse_color.rgb
which is very clear).
Could simply have diffuse_color.xyz()
function in the math library instead of truncate here
lighting::ark_light(surface_params, constants.view_params, constants.env_params).extend(input.opacity) | ||
} else { | ||
(input.diffuse_color.truncate() * input.diffuse_color.w()).extend(input.opacity) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
don't look the wording of .extend()
either, also cryptic
|
||
#[vertex_shader] | ||
fn main() -> Vec4 { | ||
let instance = instance_data[spirv::instance_index()]; // gl_InstanceIndex |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
agreed. probably should be a decorated parameter to the main function that you declare that you want to have the instance index. GLSL is not a good base here with loose globals, prefer the explicit inputs & outputs of HLSL and think that would fit better in explicit Rust land also
if instance.flags.contains(BILLBOARD_ENABLE) { | ||
let scale = extract_conservative_scale_from_transform(object_to_world); | ||
object_to_world = Mat4::from_mat3( | ||
if spirv::view_index() == 0 { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
same here with spirv::view_index
(gl_ViewIndex
), think let's try doing it as an explicit function parameter/input instead
if instance.flags.contains(ALPHA_BLENDING_ENABLE | PREMULTIPLIED_ALPHA_ENABLE) { | ||
if instance.flags.contains(PREMULTIPLIED_ALPHA_ENABLE) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
think this is pretty fine though, somewhat cleaner and less error prone to read than the GLSL switch statement with bitwise logic in it me thinks.
and for other cases Rust's match
will be really good
@repi your comments appear duplicated, any way to collapse them? |
Oh that is very odd, I think it happened somehow because I left comments in existing comments while I was doing my review, and GitHub somehow duplicates that, odd. Doesn't seem to be a way to remove it. I probably shouldn't have choosen "Request changes", but instead just "Add comments". Think it lists them as the changes I requested |
@Jasper-Bekkers think we could merge this in and file some follow up issues around the specific larger syntax discussions here? Then one can iterate further on it in future PRs |
Now that we have specific shaders to test with, we should probably close this issue and address ergonomics on a case-by-case basis. |
These are GLSL shaders we're using in Ark and versions converted into pseudo-rust.
I didn't touch on bindings yet, because I think that'll be something we can debate endlessly about.
This uses a
glam-rs
inspired math library since it seems most likely that we'll use something like that.None of this compiles / builds, but it should give a bit of an overview of how these shaders will end up looking. I think many things can be improved so I'll go through and comment on a bunch of things.
Part of #4