bevyengine / bevyengine/bevy

WGSL, i need Barycentric or Triangle-Vertex-Index

Open
#11,449 1 comment 0 reactions 0 assignees View on GitHub
A-Rendering C-Feature D-Modest S-Needs-Design
Dominant language
Rust
Stars
48.2k
Forks
4.8k
Avg merge
3d 22h
Merged PRs (30d)
161

Description

## What problem does this solve or what need does it fill?

after all, what i really need is a `@builtin(barycentric) barycoord: vec3` and `@location(2) @pervertex mtl_ids: array` in fragment shader input (p.s. primitive=triangle).
and the vertex shader output is `fn vs_main() -> @location(2) mtl_id: u16` (p.s. it doesn't need to be u16, f32 is okay, i just want say it is a flat id without fract nor varying)

so i can Blend Texture for each triangle without UV but only with `tex_ids: vec3` and `bary: vec3` in fragment shader which is pretty cool and useful for my smooth voxel game. (P.S. vertex data is like `{pos: Vec3, normal: Vec3, tex_id: u16}`)

## What solution would you like?

### Most Friendly Solution:

as said in the beginning: a `fs_main(@builtin(barycentric) barycoord: vec3` and `@location(2) @pervertex mtl_ids: array)` in fragment shader input (p.s. primitive=triangle). and the vertex shader output is `fn vs_main() -> @location(2) mtl_id: u16`

which provide Barycentric coordinate in fragment shader and provides corresponding PerVertex output in an array (for each in the primitive)

this is like (GL_EXT_fragment_shader_barycentric)[https://raw.githubusercontent.com/KhronosGroup/GLSL/master/extensions/ext/GLSL_EXT_fragment_shader_barycentric.txt] in vulkan. i.e.
```
// vertex shader:
layout(location = 2) out int MtlId;

// fragment shader:
#extension GL_EXT_fragment_shader_barycentric : enable
layout(location = 2) pervertexEXT in int in_MtlIds[3];
// builtin variable "gl_BaryCoordEXT " also provided
```

### Simplest Solution

not complex as previous, but just only provide a `@builtin(primitive_vertex_index) : u32` in vertex shader input which always produce 0,1,2 for each vertex in a triangle primitve, or provide a `@builtin(vertex_id) : u32` which always increments by 1 for each vertex even for indexed-draw, so `vertex_id % 3` will produces `primitive_vertex_index` result. (P.S. i know there has a @builtin(vertex_index):u32 variable, but it will not always increment by 1 for indexed-draw, so it cannot produce valid barycentric)

and once we have `primitive_vertex_index: u32` in vertex shader, we can produce Barycentric coordinate and passing data from vs to fs without automatic varying interpolation by a supercool trick.

```
struct MyVertexOutput {
@location(2) mtls: vec3,
@location(3) bary: vec3,
}
fn vs_main(@builtin(vertex_id) vertex_id : u32, @location(2) in_mtl_id: u32) -> MyVertexOutput {
var out: MyVertexOutput;

let primitive_vertex_index = vertex_id % 3;
let vi = primitive_vertex_index; // short name for better reading
out.bary = vec3(f32(vi == 0u), f32(vi == 1u), f32(vi == 2u)); // (1,0,0) or (0,1,0) or (0,0,1), produces BaryCoord after pass to fs
out.mtls = out.bary * vec3(in_mtl_id, in_mtl_id, in_mtl_id); // only one in_mtl_id is non-zero, other two elements are zeros.
}
fn fs_main(in: MyVertexOutput) {
let bary = in.bary;
let mtls = in.mtls / bary; // the Trick! reverse the automatic-barycentric-interpolation back to sum of mtl of 3 verts.

// success, we got the bary and mtls, lets sample texture and blending cool stuff!
}
```

note, to accomplish this, only need a new @builtin(vertex_id) is okay. which is like @builtin(vertex_index) ***in non-indexed-draw*** which is always increments by 1. so we can generate barycentric in vertex shader.

@builtin(vertex_index) is working fine only for non-indexed-draw (figure right-side), and invalid for indexed-draw (fig left-side)

![fig-invalid-vertex-index](https://github.com/bevyengine/bevy/assets/30804116/e2810b29-5e82-4cac-9a66-0893d8289ad6)
![fig-code](https://github.com/bevyengine/bevy/assets/30804116/019a692f-1f60-4486-baf4-e4ce3579768b)

## Additional context

i am working on a Smooth Voxel Sandbox Game from 2019-2024, i used Java+LWJGL3, C++&OpenGL3, C++&Vulkan and right now is Rust+Bevy+WGSL/wgpu

Repo: https://github.com/Dreamtowards/Ethertum, https://github.com/Dreamtowards/Ethertia
Work Screenshots if you intersted:

![ss-20240121005913](https://github.com/bevyengine/bevy/assets/30804116/2cd1df53-5d27-4582-8d93-3a216c04dd51)
![screenshot-20240120001806 (1)](https://github.com/bevyengine/bevy/assets/30804116/964957ab-bb34-4ab2-87e9-8d248b2351dd)

Contributor guide

Open the contributing guide

Assessment

This issue has not been assessed yet.

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.