0
\$\begingroup\$

I am using this neat Unity demo I found on Stack Overflow, which demonstrates texture masking via RenderTexture:

Can you erase a texture in real time in Unity

But the mapping from mouse position to world space is wrong. This is the script that does the mapping:

using UnityEngine;
using System.Collections;

public class MaskCamera : MonoBehaviour
{
    public Material EraserMaterial;
    private bool firstFrame;
    private Vector2? newHolePosition;

    private void CutHole(Vector2 imageSize, Vector2 imageLocalPosition)
    {
        Rect textureRect = new Rect(0.0f, 0.0f, 1.0f, 1.0f);
        Rect positionRect = new Rect(
            (imageLocalPosition.x - 0.5f * EraserMaterial.mainTexture.width) / imageSize.x,
            (imageLocalPosition.y - 0.5f * EraserMaterial.mainTexture.height) / imageSize.y,
            EraserMaterial.mainTexture.width / imageSize.x,
            EraserMaterial.mainTexture.height / imageSize.y
        );
        GL.PushMatrix();
        GL.LoadOrtho();
        for (int i = 0; i < EraserMaterial.passCount; i++)
        {
            EraserMaterial.SetPass(i);
            GL.Begin(GL.QUADS);
            GL.Color(Color.white);
            GL.TexCoord2(textureRect.xMin, textureRect.yMax);
            GL.Vertex3(positionRect.xMin, positionRect.yMax, 0.0f);
            GL.TexCoord2(textureRect.xMax, textureRect.yMax);
            GL.Vertex3(positionRect.xMax, positionRect.yMax, 0.0f);
            GL.TexCoord2(textureRect.xMax, textureRect.yMin);
            GL.Vertex3(positionRect.xMax, positionRect.yMin, 0.0f);
            GL.TexCoord2(textureRect.xMin, textureRect.yMin);
            GL.Vertex3(positionRect.xMin, positionRect.yMin, 0.0f);
            GL.End();
        }
        GL.PopMatrix();
    }

    public void Start()
    {
        firstFrame = true;
    }

    public void Update()
    {
        newHolePosition = null;
        if (Input.GetMouseButton(0))
        {
            Vector2 v = camera.ScreenToWorldPoint(Input.mousePosition);
            Rect worldRect = new Rect(-8.0f, -6.0f, 16.0f, 12.0f);
            if (worldRect.Contains(v))
                newHolePosition = new Vector2(1600 * (v.x - worldRect.xMin) / worldRect.width, 1200 * (v.y - worldRect.yMin) / worldRect.height);
        }
    }

    public void OnPostRender()
    {
        if (firstFrame)
        {
            firstFrame = false;
            GL.Clear(false, true, new Color(0.0f, 0.0f, 0.0f, 0.0f));
        }
        if (newHolePosition != null)
            CutHole(new Vector2(1600.0f, 1200.0f), newHolePosition.Value);
    }
}

I fixed line 49 and 50 like so:

Vector2 v = GetComponent<Camera>().ScreenToWorldPoint(Input.mousePosition);
Rect worldRect = new Rect(0.0f, 0.0f, 16.0f, 12.0f);

So the script compiles and the worldRect is in the right place now. Through debugging I found that the world coordinates returned on line 49 are off. I also tried setting the z value of mousePosition to 10, even though the cameras are orthographic, like so:

Vector3 mousePos = Input.mousePosition;
mousePos.z = 10;
Vector2 v = GetComponent<Camera>().ScreenToWorldPoint(mousePos);

The mapping from the mouse to worldspace is still wrong though. Mouse coordinates within a small rectangle near the center are mapping to the full width and height of the image in world space.

\$\endgroup\$

1 Answer 1

1
\$\begingroup\$

Ack! Okay, so the camera in the original script is referring to the Main Camera, not the camera with the script attached. Line 49 should read as follows:

Vector2 v = Camera.main.ScreenToWorldPoint(Input.mousePosition);

No other changes were necessary.

\$\endgroup\$

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .