Skip to content

Get sprite color in realtime #49

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

Merged
merged 1 commit into from
Oct 1, 2020
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
78 changes: 78 additions & 0 deletions Assets/Scripts/ImageEffects/SpriteColor.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

// This script gets the color of a sprite in realtime
// Usage: Attach this script to any gameobject having a sprite renderer component

public class SpriteColor : MonoBehaviour
{
public static Color GetColor { get; set; }

public SpriteRenderer targetSprite;

Color finalColor;

void Update()
{
GetSpritePixelColorUnderMousePointer(targetSprite, out finalColor);
}

public bool GetSpritePixelColorUnderMousePointer(SpriteRenderer spriteRenderer, out Color color)
{
color = new Color();
Camera cam = Camera.main;
Vector2 mousePos = Input.mousePosition;
Vector2 viewportPos = cam.ScreenToViewportPoint(mousePos);
if (viewportPos.x < 0.0f || viewportPos.x > 1.0f || viewportPos.y < 0.0f || viewportPos.y > 1.0f) return false; // out of viewport bounds

// Cast a ray from viewport point into world
Ray ray = cam.ViewportPointToRay(viewportPos);

// Check for intersection with sprite and get the color
return IntersectsSprite(spriteRenderer, ray, out color);
}

private bool IntersectsSprite(SpriteRenderer spriteRenderer, Ray ray, out Color color)
{
color = new Color();
if (spriteRenderer == null) return false;

Sprite sprite = spriteRenderer.sprite;
if (sprite == null) return false;

Texture2D texture = sprite.texture;
if (texture == null) return false;


// Craete a plane so it has the same orientation as the sprite transform
Plane plane = new Plane(transform.forward, transform.position);

// Intersect the ray and the plane
float rayIntersectDist; // the distance from the ray origin to the intersection point
if (!plane.Raycast(ray, out rayIntersectDist)) return false;

// Convert world position to sprite position
// worldToLocalMatrix.MultiplyPoint3x4 returns a value from based on the texture dimensions (+/- half texDimension / pixelsPerUnit) )
// 0, 0 corresponds to the center of the TEXTURE ITSELF, not the center of the trimmed sprite textureRect

Vector3 spritePos = spriteRenderer.worldToLocalMatrix.MultiplyPoint3x4(ray.origin + (ray.direction * rayIntersectDist));
Rect textureRect = sprite.textureRect;
float pixelsPerUnit = sprite.pixelsPerUnit;
float halfRealTexWidth = texture.width * 0.5f; // use the real texture width here because center is based on this -- probably won't work right for atlases
float halfRealTexHeight = texture.height * 0.5f;
// Convert to pixel position, offsetting so 0,0 is in lower left instead of center
int texPosX = (int)(spritePos.x * pixelsPerUnit + halfRealTexWidth);
int texPosY = (int)(spritePos.y * pixelsPerUnit + halfRealTexHeight);
// Check if pixel is within texture
if (texPosX < 0 || texPosX < textureRect.x || texPosX >= Mathf.FloorToInt(textureRect.xMax)) return false; // out of bounds
if (texPosY < 0 || texPosY < textureRect.y || texPosY >= Mathf.FloorToInt(textureRect.yMax)) return false; // out of bounds
// Get pixel color
color = texture.GetPixel(texPosX, texPosY);
GetColor = color;

return true;
}

}