-
-
Notifications
You must be signed in to change notification settings - Fork 674
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
ebiten: Create DrawImageWithShader function #1168
Comments
Shader users should not have to care about the existence of uniform variables. Updates #1168
The current situation: https://gyazo.com/ac9b83238b1133310d5830d905b2bab4 package main
var Time float
// viewportSize is a predefined function.
func Vertex(position vec2, texCoord vec2, color vec4) vec4 {
return mat4(
2.0/viewportSize().x, 0, 0, 0,
0, 2.0/viewportSize().y, 0, 0,
0, 0, 1, 0,
-1, -1, 0, 1,
) * vec4(position, 0, 1)
}
func Fragment(position vec4) vec4 {
pos := position.xy / viewportSize()
color := 0.0
color += sin(pos.x * cos(Time / 15.0) * 80.0) + cos(pos.y * cos(Time / 15.0) * 10.0)
color += sin(pos.y * sin(Time / 10.0) * 40.0) + cos(pos.x * sin(Time / 25.0) * 40.0)
color += sin(pos.x * sin(Time / 5.0) * 10.0) + sin(pos.y * sin(Time / 35.0) * 80.0)
color *= sin(Time / 10.0) * 0.5
return vec4(color, color * 0.5, sin(color + Time / 3.0 ) * 0.75, 1.0)
} |
Nice! Is the Metal implementation still planned for v1.12? 🤞🏻 |
Are you planning on making this shader language available outside of ebiten? I'm planning on trying to support Metal/Vulkan/DirectX as well, and having a go-syntax-style shader language that could work everywhere would be amazing! |
Yes!
Good question. No so far, because Ebiten requires a special hack to retrieve texels from textures (e.g., checking the region). In the future, I might fix this to be generalize for other game libraries, but I cannot guarantee. |
No worries, it’s just pretty cool stuff. I understand not wanting to maintain even more public facing APIs lol. |
In my game I found it tedious to use
Example usage: screen.DrawImageWithShader(img, shader, op)
// Would be equivelant to:
img.DrawTrianglesWithShader(vs, is, shader, op)
screen.DrawImage(img, op) Is this how the |
Yes, basically so. What I've not determined is whether to handle multiple images. One is passed as the first argument and |
Yes, that is what I implemented in my code:
|
ColorM and Filter are not used in the custom shaders.
I believe one image is used in most cases. Then one image is at an argument and three images are in the option, maybe? |
Am I understanding correctly that |
Here is my code for example: // DrawImageWithShader draws the shader to the given image, then draws the image.
func (i *Image) DrawImageWithShader(img *Image, shader *Shader, options *DrawImageWithShaderOptions) {
// Calculate the vertices
w, h := img.Size()
vs := []Vertex{
{
DstX: 0,
DstY: 0,
SrcX: 0,
SrcY: 0,
},
{
DstX: float32(w),
DstY: 0,
SrcX: float32(w),
SrcY: 0,
},
{
DstX: 0,
DstY: float32(h),
SrcX: 0,
SrcY: float32(h),
},
{
DstX: float32(w),
DstY: float32(h),
SrcX: float32(w),
SrcY: float32(h),
},
}
is := []uint16{0, 1, 2, 1, 2, 3}
// Draw the shader to the image
img.DrawTrianglesWithShader(vs, is, shader, &DrawTrianglesWithShaderOptions{
Uniforms: options.Uniforms,
Images: options.Images,
})
// Draw the image
i.DrawImage(img, &DrawImageOptions{
GeoM: options.GeoM,
ColorM: options.ColorM,
CompositeMode: options.CompositeMode,
Filter: options.Filter,
})
} |
If the shader is not drawn to the image, what about calling the function Here's an example: op := &ebiten.DrawShaderOptions{}
op.GeoM.Translate(x, y)
op.Images[0] = img
screen.DrawShader(shader, op) I think that would be more clear and simple. |
My understanding is latter. This is a counterpart for
? This seems a little ugly compared to specifying an image unfortunately :-/ |
Hmm, I see the problem there. |
I actually prefer this method, because it would allow you to set the size of the shader regardless of the size of the source image. Perhaps the width and height can be specified in |
I'd want to make the API work without specifying any options. Specifying width/height is mandatory there. I understand rendering a shader without any images is a common use case. Probably passing the width/height explicitly seems the way to go. Note that all the images must be the same size in |
Yet another idea:
|
If we separate the usage with a GeoM and without:
DrawShader renders a shader on the whole area of the target image.
|
What about specifying the width and height in the
And you can easily change them with:
|
Thank you for the suggestion! This seems a little awkward that a shader has its size, but I'm not sure. |
I said that, but I started to think this is relatively rare in actual game development compared to using an image. If so, I'd like to go with |
I think the problem is that the function gets confusing when you have more than one image. |
As there is a restriction that all the image sizes are same, I don't think this causes confusion.
Yes, but you can adjust this by GeoM.
Then the area is just enlarged like what |
I guess my only concern is that it is not very elegant to pass one image as an argument and the rest in the options. Perhaps we could have both |
Yeah, I understand you point. As the general solution is already provided by
This depends on how common rendering a shader with 0 images or >2 images compared to 1 image. My assumption is that 1 is the most common, and 0 and >2 are not so common. My assumption might be wrong, so I appreciate your opinion :-) |
Yes. I think I also think that specifying the width and height as an argument in |
I think we have reached agreement about My question is how often we need to use a shader with 0 or 2> images. If this is not so often, the existing and general |
In my game I used a shader to implement lighten blend mode by passing two images, and taking the maximum of the colors. So while passing more than one image to a shader might not be that common, it is still a valid and possible use case. I think that If you only want to have one function, and want to optimize for the use case of having only one image, then I think having |
Thanks! Actual use cases are great help to understand the situation better! Assuming rendering a rectangle area with a shader is common, what about:
? I think |
Sure, that looks great! |
… and DrawTrianglesWithShader Updates #1168
Is it possible for |
No it isn't. You'd need to create your own shader to emulate the filter like this: ebiten/internal/graphicsdriver/opengl/defaultshader.go Lines 202 to 241 in a159f55
This requires functions to get texture sizes (#1239). |
I might remove Reopened this until I decided whether to remove |
If you decide to get rid of We could implement the old idea:
|
I'm not sure, but this is definitely worth considering. The concern is |
I came up with a good idea:
|
Sounds good! I'm not sure about renaming |
maybe |
I guess renaming |
What about the name |
Oops DrawTriangles takes one image as an argument and this conflicts with multiple images in the option. Let me rethink. |
|
I like the names |
No description provided.
The text was updated successfully, but these errors were encountered: