Description
Describe the project you are working on
Godot
Describe the problem or limitation you are having in your project
Related:
One feature that is widely requested in Godot is the ability to easily have a texture and just draw to it (or even run a custom shader).
Examples of things you want to do:
Animated textures
Smoke and fire using ping-pong transfers
Water plane effects
Effects such as painting
etc.
However, the drawable texture proposal doesn't address the support for mesh/vertex shader yet.
Current MeshTexture is just a wrapper for canvas_item_add_mesh() and doesn't store texture data itself, which means it can't be used in shader uniform or 3D scene. And it can't do regional drawing.
ViewportTexture is heavy and not convenient for just rendering a simple mesh. In addition, ViewportTexture can't render 3D mesh if compling engine with 3d disabled because Node3Ds is not available.
Moreover, this is also a way to perform GPGPU using the rasterization pipeline.
Describe the feature / enhancement and how it helps to overcome the problem or limitation
Implement mesh rasterizer api and RasterizedMeshTexture. This texture accepts a mesh and a ShaderMaterial to do custom drawing.
Main differences from DrawableTexture2D:
- It supports vertex shader and vertex attributes (UV and vertex color)
- It clears the texture before each drawing, instead of blit the texture mult-times
- It only writes one color output to itself. DrawableTexture2D can write up to 4 color outputs simultaneously.
Describe how your proposal will work, with code, pseudo-code, mock-ups, and/or diagrams
My proposal PR is here: godotengine/godot#106331
Current api desgin:
enum RasterizedTextureFormat {
RASTERIZED_TEXTURE_FORMAT_RGBA8,
RASTERIZED_TEXTURE_FORMAT_RGBA8_SRGB,
RASTERIZED_TEXTURE_FORMAT_RGBAH,
RASTERIZED_TEXTURE_FORMAT_RGBAF
};
virtual RID mesh_rasterizer_create(int p_width, int p_height, RasterizedTextureFormat p_texture_format, bool p_generate_mipmaps = false) = 0;
virtual void mesh_rasterizer_set_bg_color(RID p_mesh_rasterizer, const Color &p_bg_color) = 0;
virtual void mesh_rasterizer_set_mesh(RID p_mesh_rasterizer, RID p_mesh, int p_surface_index) = 0;
virtual void mesh_rasterizer_set_material(RID p_mesh_rasterizer, RID p_material) = 0;
virtual void mesh_rasterizer_draw(RID p_mesh_rasterizer) = 0;
virtual RID mesh_rasterizer_get_texture(RID p_mesh_rasterizer) = 0;
And the core shader:
#[vertex]
#version 450
#VERSION_DEFINES
layout(set = 0, binding = 0, std430) restrict readonly buffer GlobalShaderUniformData {
vec4 data[];
}
global_shader_uniforms;
#include "samplers_inc.glsl"
layout(location = 0) in vec3 vertex_attrib;
layout(location = 1) in vec2 uv_attrib;
layout(location = 2) in vec4 color_attrib;
layout(location = 0) out vec2 uv_interp;
layout(location = 1) out vec4 color_interp;
#ifdef MATERIAL_UNIFORMS_USED
/* clang-format off */
layout(set = 1, binding = 0, std140) uniform MaterialUniforms {
#MATERIAL_UNIFORMS
}
material;
/* clang-format on */
#endif
#GLOBALS
void main() {
// Flip y-axis and convert z-axis to [0,1].
mat4 m = mat4(
1.0, 0.0, 0.0, 0.0,
0.0, -1.0, 0.0, 0.0,
0.0, 0.0, 0.5, 0.0,
0.0, 0.0, 0.5, 1.0);
vec4 vertex = m * vec4(vertex_attrib, 1);
vec2 uv = uv_attrib;
vec4 color = color_attrib;
{
#CODE : VERTEX
}
uv_interp = uv;
color_interp = color;
gl_Position = vertex;
}
#[fragment]
#version 450
#VERSION_DEFINES
layout(set = 0, binding = 0, std430) restrict readonly buffer GlobalShaderUniformData {
vec4 data[];
}
global_shader_uniforms;
#include "samplers_inc.glsl"
layout(location = 0) in vec2 uv_interp;
layout(location = 1) in vec4 color_interp;
layout(location = 0) out vec4 frag_color;
#ifdef MATERIAL_UNIFORMS_USED
/* clang-format off */
layout(set = 1, binding = 0, std140) uniform MaterialUniforms {
#MATERIAL_UNIFORMS
}
material;
/* clang-format on */
#endif
#GLOBALS
void main() {
vec2 uv = uv_interp;
vec4 color = color_interp;
{
#CODE : FRAGMENT
}
frag_color = color;
}
And a new resource RasterizedMeshTexture, which is a wrapper of RenderingServer api.
If this enhancement will not be used often, can it be worked around with a few lines of script?
This can be worked around using RenderingDevice ( See also https://github.com/beicause/GodotMeshTextureRd ), but not convenient
Is there a reason why this should be core and not an add-on in the asset library?
It's core