#Ok so then I would try a basic
1 messages · Page 1 of 1 (latest)
in order not to pollute the chat, you can discuss in a separate thread
still just an empty texture ((
[Button]
public void MeshToSpriteV3()
{
Texture2D texture = meshRenderer.material.mainTexture as Texture2D;
Texture2D spriteTexture = new Texture2D(texture.width, texture.height, TextureFormat.RGBA32, false);
var duplicateTexture = GetRenderTextureWithMesh(texture);
RenderTexture previous = RenderTexture.active;
RenderTexture.active = duplicateTexture;
Graphics.SetRenderTarget(duplicateTexture);
spriteTexture.ReadPixels(new Rect(0, 0, duplicateTexture.width, duplicateTexture.height), 0, 0);
spriteTexture.Apply();
byte[] spriteData = spriteTexture.EncodeToPNG();
File.WriteAllBytes(savePath, spriteData);
RenderTexture.active = previous;
RenderTexture.ReleaseTemporary(duplicateTexture);
}
RenderTexture GetRenderTextureWithMesh(Texture2D source)
{
RenderTexture renderTex = RenderTexture.GetTemporary(
source.width,
source.height,
0,
RenderTextureFormat.Default,
RenderTextureReadWrite.Linear);
// Graphics.Blit(source, renderTex);
RenderTexture previous = RenderTexture.active;
RenderTexture.active = renderTex;
Graphics.SetRenderTarget(renderTex);
GL.PushMatrix();
GL.LoadOrtho();
// material.SetPass(0);
Graphics.DrawMeshNow(MeshFilter.mesh, Vector3.zero, Quaternion.identity, 0);
GL.Clear(true, true, Color.clear);
RenderTexture.active = previous;
RenderTexture.ReleaseTemporary(renderTex);
GL.PopMatrix();
return renderTex;
}
It doesn't help that you're clearing after drawing the mesh. That guarantees you get nothing.
I said after the SetRenderTarget
Also the material.SetPass(0) line is commented out, I'm assuming because you didn't know what material to use. You're not going to get anything if you don't have a material to render with. Otherwise it doesn't know what texture to draw the mesh with.
🫡
I specified the last parameter in the DrawMeshNow method
The 0?
I don't know why it's called materialIndex, because it's referring to submesh.
It defaults to 0 if unspecified.
)
You still need to call material.SetPass(0). A mesh doesn't have any material connected to it which can be referred by index like this.
MeshRenderer.material.SetPass(0)?
Sure
Ok, let's try moving the orthographic projection a bit then.
The GL.LoadOrtho() gets replaced with:
GL.LoadProjectionMatrix(Matrix4x4.Ortho(-1, 1, -1, 1, -1, 100))
For reference, GL.LoadOrtho uses Matrix4x4.Ortho(0, 1, 0, 1, -1, 100), so we're moving the XY range from (0, 1) to (-1, 1)
Ok, it looks about half the size, so I think a range of (-0.5f, 0.5f) might work: Matrix4x4.Ortho(-0.5f, 0.5f, -0.5f, 0.5f, -1, 100)
This is the other half?
That number is also close to half the square root of 2, which unfortunately is an irrational number, but might be close enough:
0.7071067
I don't know why it would be that. It really all depends on how the asset you're using generates the vertices.
With a custom shader, you could also use the UV instead of the vertex positions, assuming those don't already match.
how to calculate this?
Mathf.Sqrt(2) * 0.5f
- it still ends up being a little smaller
- and another question, is it possible to make a square grid with two triangles as in the original image?
- as I understand it, it is important that the object, when rendered into a texture, be at coordinates 0 0 0 with a scale of 1 1 1?
- And I'm a little embarrassed that the quality has become a little worse (
You're not going to use this sliced mesh for anything but to generate the separate sprite assets, right? Unity will reimport the texture and generate its own mesh.
I'm going to continue to use sprites in the gameplay, and the mesh and asset only for cutting
Try using this shader instead of Sprite/Default. The matrix will probably have to be changed to line it back up. Note, this shader is only intended for this custom rendering we're doing. It's not a replacement for the shader you're using on the SpriteRenderer, so you will have to change the code to separate those two.
That's the extent of what I'm going to do for you. I'm not sure what you're trying to do makes sense.
those. on an object with a mesh renderer before rendering to a texture, do I need to set this shader? and then when using the final sprite in runtime, you can use Sprite/Default?
This material doesn't need to be put on a mesh renderer. You can just make a material with this shader, put the right texture on it, either by hand or through script, and then call SetPass(0) on it.
And it's only used in this case to generate the texture. You can use whatever shader you want after that to display the generated texture.
then there will be no deterioration in quality?
That's the goal
I'm going to try now
like this ?
That looks right.
I tried to render with this material, but for some reason the sprite is shifted to the side and up, in the second case, when I commented out the actions with the material, it was rendered in the right place, but without a texture (which is logical)
the quality is still the same
As I said, the ortho matrix likely will have to be edited to line it up again.
(0, 1) might work this time.
As for the quality, this part can never be as "high" quality as the sliced mesh, because you're not looking at pixels on the sliced mesh. It's a mesh, so you can zoom in infinitely and it will stay sharp.
But the texture itself within the mesh should stay the same quality. If not, then it might be due to compression when encoding it to a PNG.
Again, I want to be sure you're not talking about the right side being pixelated, right?
I mean the right side of the right sprite, this part:
You would need to increase the size of the render texture if you want that side to be sharper.
If you just look at the pixels within the original sliced mesh, they look very similar, maybe a little bit of extra compression because of the PNG export and the additional compression when importing into Unity.
it is similar to sprite)
You're taking a compressed picture, exporting a portion of it, then importing it back into Unity, which compresses it again.
You can disable compression in the texture import settings.
I understand correctly that before starting rendering, I need to set the position of my object with the mesh renderer to 0 0 0 and the scale to 1 1 1 and the rotation to 0 0 0?
No, the mesh renderer has nothing to do with this process.
You could delete it if you wanted to. We just need the Mesh and material.
Yes, the renderer. It has nothing to do with the process. We're just getting the mesh and the material from it.
it turned out cool, thank you very much, now I’ll figure out how it generally works in more detail. If so, can I ask you questions about how it works in this thread?
Sure.
RenderTexture.active = renderTex;
Graphics.SetRenderTarget(renderTex);
both do the same thing, you only have to call either one.
and why use this material for rendering with this shader? what did he give us in the end?
The shader I made ignores the vertex positions of the mesh and just uses their texture coordinates to position them correctly. That way, it doesn't matter what weird stuff the mesh slice asset is doing with the vertex positions, the mesh will always be drawn in the correct position according to the texture.