-
Notifications
You must be signed in to change notification settings - Fork 15
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
How to use alpha? #20
Comments
Unfortunately, the current master branch doesn't really support blending. However, thankfully, the new You can see that in the |
What happens if you disable culling entirely? Do you still get the problems? Also, how is the text generated? Is it made of lots of small polygons, or a larger one with a texture? |
How can I disable culling? I thought passing // Old code
Triangle{...}.draw::<rasterizer::Triangles<(f32,), euc::rasterizer::BackfaceCullingDisabled>, _>(index_buffer, pixel.into(), None);
// New code
Triangle{...}.render(index_buffer, euc::CullMode::None, pixel.into(), &mut euc::Empty::default());
Its made with larger one with a texture. So fuzziness is very likely caused by bad blending still. However, at least blending is partially working already. Tried to debug some: The fragment shader always produced red. The global variable to count calls did not use mutex or similar, so if threading is used on the refactor branch, then the data is bogus. |
Do you have a minimal example I can take a look at locally? It might be an issue on my end that I've managed to miss while testing. |
To be clear, I assume the text issue is caused by my code not being complete yet. Here is code that tries to draw the background rectangle only. refactor branch (unexpected): use euc::{buffer::Buffer2d, rasterizer, Pipeline};
use minifb;
use euc::{buffer::*, CullMode, Target};
use vek::*;
struct Triangle {
dimensions: [f32; 2],
vertex_buffer: Vec<[f32; 2]>,
}
impl Pipeline for Triangle {
type Vertex = u32;
type VertexData = f32;
type Pixel = u32;
type Primitives = euc::TriangleList;
type Fragment = f32;
#[inline(always)]
fn vertex_shader(&self, vertex_index: &Self::Vertex) -> ([f32; 4], Self::VertexData) {
let vertex_xy = self.vertex_buffer[*vertex_index as usize];
let ret = [
2.0 * vertex_xy[0] / self.dimensions[0] - 1.0,
1.0 - 2.0 * vertex_xy[1] / self.dimensions[1],
0.0,
1.0,
];
(ret, 0.0)
}
#[inline(always)]
fn fragment_shader(&self, vs_out: Self::VertexData) -> Self::Fragment {
0.0
}
fn blend_shader(&self, old: Self::Pixel, new: Self::Fragment) -> Self::Pixel {
// RED
(255 as u32) << 24 | (255 as u32) << 16 | (0 as u32) << 8 | (0 as u32) << 0
}
}
const W: usize = 800;
const H: usize = 600;
fn main() {
let mut win =
minifb::Window::new("Minimal example", W, H, minifb::WindowOptions::default()).unwrap();
while win.is_open() {
let mut color = Buffer2d::fill([W, H], 0);
// vertex positions [x,y]
let vertex_buffer = vec![[0.5, 0.5], [223.5, 0.5], [223.5, 599.5], [0.5, 599.5]];
let index_buffer = [1, 0, 2, 2, 0, 3];
Triangle {
vertex_buffer,
dimensions: [W as f32, H as f32],
}
.render(
index_buffer,
euc::CullMode::None,
&mut color,
&mut euc::Empty::default(),
);
win.update_with_buffer(color.raw(), W, H).unwrap();
}
} default branch (expected): use euc::buffer::Buffer2d;
use minifb;
use egui::{
color::*,
emath::Rect,
epaint::{Color32, Mesh},
Texture,
};
use euc::{buffer::*, rasterizer, DepthStrategy, Pipeline, Target};
use image::{RgbImage, RgbaImage};
use std::path::Path;
use vek::*;
struct Triangle {
dimensions: [f32; 2],
vertex_buffer: Vec<[f32; 2]>,
}
impl Pipeline for Triangle {
type Vertex = u32;
type VsOut = f32;
type Pixel = u32;
#[inline(always)]
fn vert(&self, vertex_index: &Self::Vertex) -> ([f32; 4], Self::VsOut) {
let vertex_xy = self.vertex_buffer[*vertex_index as usize];
let ret = [
2.0 * vertex_xy[0] / self.dimensions[0] - 1.0,
1.0 - 2.0 * vertex_xy[1] / self.dimensions[1],
0.0,
1.0,
];
(ret, 0.0)
}
#[inline(always)]
fn get_depth_strategy(&self) -> DepthStrategy {
DepthStrategy::None
}
#[inline(always)]
fn frag(&self, out: &Self::VsOut) -> Self::Pixel {
// RED
(255 as u32) << 24 | (255 as u32) << 16 | (0 as u32) << 8 | (0 as u32) << 0
}
}
const W: usize = 800;
const H: usize = 600;
fn main() {
let mut win =
minifb::Window::new("Minimal example", W, H, minifb::WindowOptions::default()).unwrap();
while win.is_open() {
let mut color = Buffer2d::new([W, H], 0);
// vertex positions [x,y]
let vertex_buffer = vec![[0.5, 0.5], [223.5, 0.5], [223.5, 599.5], [0.5, 599.5]];
let index_buffer = [1, 0, 2, 2, 0, 3];
Triangle {
vertex_buffer,
dimensions: [W as f32, H as f32],
}
.draw::<rasterizer::Triangles<(f32,), euc::rasterizer::BackfaceCullingDisabled>, _>(
&index_buffer,
&mut color,
None,
);
win.update_with_buffer(color.as_ref(), W, H).unwrap();
}
} |
Those triangles have an opposing winding order. If you change the index buffer to Edit: I've just tried it myself and it seems to. This seems like a culling bug, I'll fix it now. |
I've fixed this issue in 3b23507, it seems to render correctly now. Thanks for pointing this out! This also reminded me that I push the |
Now the background issue is fixed, but the text is missing half of each rectangle. (see last image of #20 (comment)) |
To me, this looks like a blending issue. It appears that the source pixels aren't being smoothly blended with the target, they're being binary blended past a specific threshold. |
It's still culling triangles? That's quite bizarre. I'll definitely be writing some tests for this once we've gotten to the bottom of this problem. |
Here is the data. It has the index buffer and vertex buffer. You can replace the data of the buffers in the examples in #20 (comment) and run the code to see the results. Use latest refactor branch and euc 5.3. The result should look like the two images in #20 (comment) |
Thanks, I'll try to get to this over the weekend. |
I did a git bisect on the original issue related to the background triangle not being rendered. The commit does not seem to include references to winding. So it is possible that the winding is fine and the problem is elsewhere. Here is bisect log
Here is the code for that bad commit that I expect to render a single red rectangle, but instead renders a triangle. // a13bd8c
use euc::{buffer::Buffer2d, rasterizer, Pipeline};
use minifb;
use euc::{buffer::*, CullMode, Target};
use vek::*;
struct Triangle {
dimensions: [f32; 2],
vertex_buffer: Vec<[f32; 2]>,
}
impl Pipeline for Triangle {
type Vertex = u32;
type VertexData = f32;
type Pixel = u32;
type Primitives = euc::TriangleList;
// type Fragment = f32;
#[inline(always)]
fn vertex_shader(&self, vertex_index: &Self::Vertex) -> ([f32; 4], Self::VertexData) {
let vertex_xy = self.vertex_buffer[*vertex_index as usize];
let ret = [
2.0 * vertex_xy[0] / self.dimensions[0] - 1.0,
1.0 - 2.0 * vertex_xy[1] / self.dimensions[1],
0.0,
1.0,
];
(ret, 0.0)
}
#[inline(always)]
fn fragment_shader(&self, vs_out: Self::VertexData) -> Self::Pixel {
0
}
fn blend_shader(&self, old: Self::Pixel, new: Self::Pixel) -> Self::Pixel {
// RED
(255 as u32) << 24 | (255 as u32) << 16 | (0 as u32) << 8 | (0 as u32) << 0
}
}
const W: usize = 800;
const H: usize = 600;
fn main() {
let mut win =
minifb::Window::new("Minimal example", W, H, minifb::WindowOptions::default()).unwrap();
while win.is_open() {
let mut color = Buffer2d::fill([W, H], 0);
// vertex positions [x,y]
let vertex_buffer = vec![[0.5, 0.5], [223.5, 0.5], [223.5, 599.5], [0.5, 599.5]];
let index_buffer = [1, 0, 2, 2, 0, 3];
Triangle {
vertex_buffer,
dimensions: [W as f32, H as f32],
}
.render(
index_buffer,
euc::CullMode::None,
&mut color,
&mut euc::Empty::default(),
);
win.update_with_buffer(color.raw(), W, H).unwrap();
}
} |
Just bumping this since I don't want to create a new issue for something that's technically only a problem on a wip branch. The last snippet shared by OP currently correctly produces a rectangle, but when you change the order of the indices you get a single triangle again, so it looks like it's still broken. |
I'd be interested to know whether this is still an issue on the |
Sorry, yes, that's what I meant by WIP branch. I'm running into this as of the latest commit of My understanding is that in the rectangle example with rasterizer_config returning CullMode::None, I should be able to get a solid rectangle regardless of the order of indices within a single triangle. While that snippet works as-is (adjusted for api changes), if I change the order of the first triangle's indices to be clockwise: |
Any chance you could post the snippet here? I can look into this tomorrow. |
Sure, it's just the code from #20 (comment) adjusted for API changes and with swapped indices on the first triangle: use euc::{buffer::Buffer2d, CullMode, Pipeline, TriangleList};
struct Triangle {
dimensions: [f32; 2],
vertex_buffer: Vec<[f32; 2]>,
}
impl Pipeline for Triangle {
type Vertex = u32;
type VertexData = f32;
type Pixel = u32;
type Primitives = TriangleList;
type Fragment = f32;
fn rasterizer_config(&self) -> CullMode {
CullMode::None
}
#[inline(always)]
fn vertex(&self, vertex_index: &Self::Vertex) -> ([f32; 4], Self::VertexData) {
let vertex_xy = self.vertex_buffer[*vertex_index as usize];
let ret = [
2.0 * vertex_xy[0] / self.dimensions[0] - 1.0,
1.0 - 2.0 * vertex_xy[1] / self.dimensions[1],
0.0,
1.0,
];
(ret, 0.0)
}
#[inline(always)]
fn fragment(&self, _vs_out: Self::VertexData) -> Self::Fragment {
0.0
}
#[inline(always)]
fn blend(&self, _old: Self::Pixel, _new: Self::Fragment) -> Self::Pixel {
// RED
(255_u32) << 24 | (255_u32) << 16
}
}
const W: usize = 800;
const H: usize = 600;
fn main() {
let mut win =
minifb::Window::new("Minimal example", W, H, minifb::WindowOptions::default()).unwrap();
while win.is_open() {
let mut color = Buffer2d::fill([W, H], 0);
let vertex_buffer = vec![[0.5, 0.5], [223.5, 0.5], [223.5, 599.5], [0.5, 599.5]];
let index_buffer = [0, 1, 2, 2, 0, 3];
Triangle {
vertex_buffer,
dimensions: [W as f32, H as f32],
}
.render(index_buffer, &mut color, &mut euc::Empty::default());
win.update_with_buffer(color.raw(), W, H).unwrap();
}
} |
Right, I found the bug and pushed a fix. It was really quite subtle and depended on the fact that the y coordinates of the upper two vertices are the same, but all seems to work now. |
Woo, that's good to hear :) Very cool that you're using |
By the way, the |
Haha. Cool stuff. 😃
I think so. IIRC the only things needed are texture support, alpha blending. Both are available, at least on the refactor branch. Take a peek at the integration part here, only the "paint" function needs to be coded https://docs.rs/egui/latest/egui/index.html#integrating-with-egui The user would need to gather all the inputs and pass them to egui. Egui would produce the triangles. The euc backend (Paint function) could take in the triangles and textures, render it and output the end result. The user would then need to decide what to do with the rendered output and how to display it. |
Interesting stuff!
I can imagine this being the case. Opportunities for compiler optimisations are even narrower on WASM than on other targets right now, and |
I am trying to render triangles that use alpha. However, my tests indicate that alpha is not taken into account by the rendering pipeline.
I am using euc 0.5.3
I took the example code and made it render two triangles on top of each other. One is red and one is blue.
Changing the alpha value of the red or blue color does not change the output in any way.
Is there some setting I am missing? I did not stumble on any examples regarding alpha and could not find anything regarding it in the documentation. However, the following issue mentions alpha blending: #9
Here is my code, which is the triangle example modified.
And here is an image of the result
The text was updated successfully, but these errors were encountered: