Skip to content

Instantly share code, notes, and snippets.

@MattRix
Last active November 12, 2015 15:31
Show Gist options
  • Star 2 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save MattRix/a149ee6776801e613f5e to your computer and use it in GitHub Desktop.
Save MattRix/a149ee6776801e613f5e to your computer and use it in GitHub Desktop.
Photobomb painting code
using UnityEngine;
using System.Collections;
using System.Collections.Generic;
using System;
public class Bench : MonoBehaviour
{
static public bool SHOULD_DEBUG = true;
static public Color defaultColor = Color.white;
public Vector2 simPos;
public Obstacle obstacle;
public float radius = 1f;
public float angle = 0;
public Vector2 dropPos;
public float dropRadius = 0.2f;
public Backpack backpack;
public BenchColor benchColor;
static public Bench Create()
{
var benchGO = new GameObject("Bench");
var bench = benchGO.GetComponent<Bench>();
if(bench == null) bench = benchGO.AddComponent<Bench>();
bench.obstacle = Obstacle.Create(ObstacleType.Bench);
bench.gameObject.isStatic = true;
return bench;
}
public void Setup(BenchColor benchColor, Vector2 simPos, float angle)
{
this.benchColor = benchColor;
this.simPos = simPos;
this.angle = angle;
obstacle.Setup(simPos,angle);
this.transform.position = new Vector3(simPos.x,0,simPos.y);
this.transform.rotation = Quaternion.AngleAxis(angle,Vector3.down);
obstacle.transform.parent = this.transform;
obstacle.renderer.material.color = benchColor.color;
dropPos = simPos + new Vector2(0.5f,0.0f).RotateDegrees(angle-90f);
}
public void EndSimulation()
{
obstacle.renderer.material = benchColor.paintMaterial.material;
}
public void OnDrawGizmos()
{
var pos3D = this.transform.position;
GizmoUtils.DrawWireDisc(pos3D,Vector3.up,radius);
Gizmos.color = Color.blue;
GizmoUtils.DrawWireDisc(new Vector3(dropPos.x,0,dropPos.y),Vector3.up,dropRadius);
}
}
public class BenchColor
{
static public Material materialAsset;
static public List<BenchColor> allColors = new List<BenchColor>();
static public BenchColor Red = new BenchColor("Red",0xFF0033);
static public BenchColor Orange = new BenchColor("Orange",0xFF9900);
static public BenchColor Yellow = new BenchColor("Yellow",0xFFFF00);
static public BenchColor Green = new BenchColor("Green",0x33FF00);
static public BenchColor Blue = new BenchColor("Blue",0x0066FF);
static public BenchColor Purple = new BenchColor("Purple",0x9900FF);
public string name;
public Color color;
public int index;
public PaintMaterial paintMaterial;
public BenchColor(string name, uint hexColor)
{
this.name = name;
this.color = RXColor.GetColorFromHex(hexColor);
this.index = allColors.Count;
if(materialAsset == null)
{
materialAsset = Resources.Load<Material>("Materials/PawnMat");
}
paintMaterial = new PaintMaterial(materialAsset,this.color);
allColors.Add(this);
}
}
using UnityEngine;
using System.Collections;
using System.Collections.Generic;
using System;
public class Painter
{
static Painter instance;
static public Painter GetInstance()
{
if(instance == null)
{
instance = new Painter();
}
return instance;
}
public GameObject go;
public Camera camera;
public Shader shader;
public Painter()
{
go = new GameObject("Painter");
camera = go.AddComponent<Camera>();
camera.enabled = false; //don't render normally
shader = Shader.Find("Photobomb/UVShader");
}
public void Paint(Camera referenceCamera)
{
camera.CopyFrom(referenceCamera);
camera.rect = new Rect(0,0,1.0f,1.0f); //full rect
if(GameConfig.SHOULD_PAINT_ONLY_IN_FRAME)
{
camera.fieldOfView = GameConfig.PHOTO_FOV;
}
ActuallyPaint();
// camera.transform.position = camera.transform.position + new Vector3(0.01f,0.01f,0.01f); //move it a bit and paint again
// camera.transform.Rotate(0.1f,0.1f,0.1f);
// ActuallyPaint();
}
void ActuallyPaint()
{
int width = Mathf.RoundToInt((float)GameConfig.PHOTO_WIDTH * GameConfig.PAINT_RENDERTEXTURE_RATIO);
int height = Mathf.RoundToInt((float)GameConfig.PHOTO_HEIGHT * GameConfig.PAINT_RENDERTEXTURE_RATIO);
camera.SetReplacementShader(shader,"");
camera.clearFlags = CameraClearFlags.Color;
camera.backgroundColor = Color.black;
var rt = RenderTexture.GetTemporary(width,height,16,RenderTextureFormat.ARGB32,RenderTextureReadWrite.Linear);
camera.targetTexture = rt;
camera.Render();
camera.targetTexture = null;
var prevRT = RenderTexture.active;
RenderTexture.active = rt;
var tex = new Texture2D(width,height,TextureFormat.RGB24,false,true);
tex.ReadPixels(new Rect(0,0,width,height),0,0);
tex.Apply();
ProcessPic(tex);
RenderTexture.active = prevRT;
RenderTexture.ReleaseTemporary(rt);
Texture2D.Destroy(tex);
}
void ProcessPic (Texture2D tex)
{
var pixels = tex.GetPixels32(0);
int pixelCount = pixels.Length;
var paintMats = PaintMaterial.allPaintMaterials;
int matCount = paintMats.Count;
List<Vector2>[] paintUVs = new List<Vector2>[matCount];
for(int m = 0; m<matCount; m++)
{
paintUVs[m] = new List<Vector2>(100);
}
for(int p = 0; p<pixelCount; p++)
{
var pixel = pixels[p];
if(pixel.b != 0)
{
if(pixel.b <= matCount)
{
paintUVs[pixel.b-1].Add(new Vector2((float)pixel.r/255f,(float)pixel.g/255f));
}
}
}
//go through all the materials and apply the painted UVs to them
for(int m = 0; m<matCount; m++)
{
var uvs = paintUVs[m];
int uvCount = uvs.Count;
if(uvCount > 0) //don't paint textures that we weren't in the picture
{
var targetTex = paintMats[m].texture;
var paintColor = paintMats[m].paintColor;
float targetWidth = targetTex.width;
float targetHeight = targetTex.height;
for(int s = 0; s<uvCount; s++)
{
int drawX = (int)(uvs[s].x*targetWidth);
int drawY = (int)(uvs[s].y*targetHeight);
//paint all 5 pixels around the target
targetTex.SetPixel(drawX,drawY,paintColor);
targetTex.SetPixel(drawX+1,drawY,paintColor);
targetTex.SetPixel(drawX,drawY+1,paintColor);
targetTex.SetPixel(drawX-1,drawY,paintColor);
targetTex.SetPixel(drawX,drawY-1,paintColor);
}
targetTex.Apply();
}
}
}
}
using UnityEngine;
using System.Collections;
using System.Collections.Generic;
using System;
public class PaintMaterial
{
static public List<PaintMaterial> allPaintMaterials = new List<PaintMaterial>();
public int index;
public float objectID;
public Material material;
public Texture2D texture;
public Color paintColor;
public PaintMaterial(Material referenceMaterial, Color paintColor)
{
index = allPaintMaterials.Count;
allPaintMaterials.Add(this);
objectID = (float)(index+1);
this.paintColor = paintColor;
material = Material.Instantiate(referenceMaterial) as Material;
texture = new Texture2D(GameConfig.PAINT_TEXTURE_SIZE,GameConfig.PAINT_TEXTURE_SIZE,TextureFormat.RGB24,false);
material.mainTexture = texture;
material.SetFloat("_ObjectID",objectID);
ClearTexture();
}
public void ClearTexture()
{
int pixelCount = texture.width*texture.height;
Color32[] colors = new Color32[pixelCount];
Color32 clearColor = (Color32)Color.white;
for(int c = 0; c<pixelCount; c++)
{
colors[c] = clearColor;
}
texture.SetPixels32(colors);
texture.Apply();
}
static public void ClearAll()
{
foreach(var mat in allPaintMaterials)
{
mat.ClearTexture();
}
}
}
Shader "Photobomb/UVShader"
{
Properties
{
_MainTex ("Base (RGB)", 2D) = "white" {}
_ObjectID ("Object ID", Float) = 0
}
SubShader
{
Pass
{
Fog { Mode Off }
Tags { "LightMode" = "ForwardBase" }
CGPROGRAM
#pragma vertex vert
#pragma fragment frag
uniform sampler2D _MainTex;
uniform float _ObjectID;
struct vertexInput
{
float4 pos : POSITION;
float2 uv : TEXCOORD0;
};
struct vertexOutput
{
float4 pos : SV_POSITION;
float2 uv : TEXCOORD0;
};
vertexOutput vert (vertexInput i)
{
vertexOutput o;
o.pos = mul(UNITY_MATRIX_MVP, i.pos);
o.uv = i.uv;
return o;
}
float4 frag (vertexOutput o) : COLOR
{
if(_ObjectID <= 0.0)
{
return float4(0.0,0.0,0.0,1.0);
}
else
{
return float4(o.uv.x,o.uv.y,_ObjectID/255.0,1.0);
}
}
ENDCG
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment