当前位置:网站首页>Introduction to graphics: graphic painting (I)
Introduction to graphics: graphic painting (I)
2022-07-04 01:47:00 【Yangyang 2035】
Recently, I want to realize a series of painting functions , I think it's very useful .
The first is ordinary color rendering , Use material texture to paint , as follows :
Suppose there is a texture on it uv, Our mouse rays hit muv, according to radius Calculate the drawn circumscribed rectangle rect, Then judge the circle coloring according to the distance from the arc to the center of the circle . The only thing to pay attention to here is the boundary of texture pixels , Don't cross the line , as follows :
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class TestColorSpray : MonoBehaviour
{
public Color color; // Color
[Range(0, 1)]
public float alpha; // transparency
public int radius; // Radius pixels
private Camera cam;
private bool isStart = false;
private Material mat;
private Texture2D tex;
private int texWidth;
private int texHeight;
void Start()
{
cam = Camera.main;
}
void FixedUpdate()
{
if (Input.GetMouseButtonDown(0))
{
Ray ray = cam.ScreenPointToRay(Input.mousePosition);
RaycastHit hit;
if (Physics.Raycast(ray, out hit))
{
StartSpray(hit.transform);
}
}
if (Input.GetMouseButton(0))
{
if (isStart)
{
Ray ray = cam.ScreenPointToRay(Input.mousePosition);
RaycastHit hit;
if (Physics.Raycast(ray, out hit))
{
#if UNITY_EDITOR
Debug.DrawLine(cam.transform.position, hit.point, Color.black);
#endif
// Mouse Center
Vector2 muv = new Vector2(hit.textureCoord.x * texWidth, hit.textureCoord.y * texHeight);
int mx = Mathf.Clamp((int)muv.x, 0, texWidth - 1);
int my = Mathf.Clamp((int)muv.y, 0, texHeight - 1);
// Outside rectangle ( Irregular )
int left = Mathf.Clamp(mx - radius, 0, texWidth - 1);
int right = Mathf.Clamp(mx + radius, 0, texWidth - 1);
int bottom = Mathf.Clamp(my - radius, 0, texHeight - 1);
int top = Mathf.Clamp(my + radius, 0, texHeight - 1);
int rectwid = right - left;
int recthei = top - bottom;
// draw
Color[] ogcols = tex.GetPixels(left, bottom, rectwid, recthei);
// progressive scanning
for (int y = 0; y < recthei; y++)
{
for (int x = 0; x < rectwid; x++)
{
int index = y * rectwid + x;
int px = x + left - mx;
int py = y + bottom - my;
float alphainten;
if (CheckInCircle(radius, px, py, out alphainten))
{
Color ocol = ogcols[index];
Color scol = color;
float inten = alphainten * alpha;
ogcols[index] = BlendColor(ocol, scol, inten);
}
}
}
tex.SetPixels(left, bottom, rectwid, recthei, ogcols);
tex.Apply();
}
}
}
if (Input.GetMouseButtonUp(0))
{
StopSpray();
}
}
private void StartSpray(Transform obj)
{
isStart = true;
mat = obj.GetComponent<MeshRenderer>().sharedMaterial;
tex = (Texture2D)mat.GetTexture("_MainTex");
texWidth = tex.width;
texHeight = tex.height;
}
private void StopSpray()
{
isStart = false;
}
/// <summary>
/// testing xy stay rad Circular middle
/// Relative coordinates , center of a circle (0,0)
/// </summary>
/// <param name="rad"></param>
/// <param name="x"></param>
/// <param name="y"></param>
/// <param name="inten"></param>
/// <returns></returns>
private bool CheckInCircle(int rad, int x, int y, out float inten)
{
float rad2 = rad * rad;
float len2 = x * x + y * y;
inten = 1f - len2 / rad2;
return len2 <= rad2;
}
/// <summary>
/// Mix colors
/// </summary>
/// <param name="a"></param>
/// <param name="b"></param>
/// <returns></returns>
private Color BlendColor(Color a, Color b, float k)
{
Color c = Color.Lerp(a, b, k);
return c;
}
}
Test it ,material Of maintex Set to readwrite/rgba32, as follows :
But there's a small problem , It is suggested to make a copy of the material picture , Otherwise Apply Covering the original data , as follows :
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class SprayObject : MonoBehaviour
{
void Start()
{
MeshRenderer render = gameObject.GetComponent<MeshRenderer>();
Material mat = render.material;
Texture2D tex = (Texture2D)mat.GetTexture("_MainTex");
Texture2D copytex = new Texture2D(tex.width, tex.height, tex.format, false);
copytex.SetPixels(tex.GetPixels());
copytex.Apply();
mat.SetTexture("_MainTex", copytex);
}
}
In this way, the objects we spray on first clone A material and map .
At the same time, there is a big problem in this scheme , That's it uv Joints cannot be treated , as follows :
Because of the uv Is discontinuous and random ( According to the artists uvmapping) Of , Therefore, the continuity of spraying cannot be handled , If it's true , We have to think of another spraying scheme .
Of course, the current plan also has a certain place to play , For example, brush the terrain 、 Brush objects , I use this .
There are also brush patterns and textures , as follows :
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class TestGraphSpray : MonoBehaviour
{
public Texture2D graphTex; // pattern
[Range(0, 1)]
public float alpha; // transparency
private Camera cam;
private bool isStart = false;
private Material mat;
private Texture2D tex;
private int texWidth;
private int texHeight;
private int gWid; // The pattern is wide
private int gHei; // The pattern is high
private int ghWid; // Pattern half width
private int ghHei; // The pattern is half height
void Start()
{
cam = Camera.main;
gWid = graphTex.width;
gHei = graphTex.height;
ghWid = (int)(gWid * 0.5f);
ghHei = (int)(graphTex.height * 0.5f);
}
void Update()
{
if (Input.GetMouseButtonDown(0))
{
Ray ray = cam.ScreenPointToRay(Input.mousePosition);
RaycastHit hit;
if (Physics.Raycast(ray, out hit))
{
StartSpray(hit.transform);
}
}
if (Input.GetMouseButton(0))
{
if (isStart)
{
Ray ray = cam.ScreenPointToRay(Input.mousePosition);
RaycastHit hit;
if (Physics.Raycast(ray, out hit))
{
#if UNITY_EDITOR
Debug.DrawLine(cam.transform.position, hit.point, Color.black);
#endif
// Mouse Center
Vector2 muv = new Vector2(hit.textureCoord.x * texWidth, hit.textureCoord.y * texHeight);
int mx = Mathf.Clamp((int)muv.x, 0, texWidth - 1);
int my = Mathf.Clamp((int)muv.y, 0, texHeight - 1);
// Outside rectangle ( Irregular )
int left = Mathf.Clamp(mx - ghWid, 0, texWidth - 1);
int right = Mathf.Clamp(mx + ghWid, 0, texWidth - 1);
int bottom = Mathf.Clamp(my - ghHei, 0, texHeight - 1);
int top = Mathf.Clamp(my + ghHei, 0, texHeight - 1);
int rectwid = right - left;
int recthei = top - bottom;
// draw
Color[] ocols = tex.GetPixels(left, bottom, rectwid, recthei);
// According to whether the rectangle is out of bounds , Judge graphTex Starting point of sampling
int gx = mx > ghWid ? 0 : ghWid - mx;
int gy = my > ghHei ? 0 : ghHei - my;
Color[] gcols = graphTex.GetPixels(gx, gy, rectwid, recthei);
// progressive scanning
for (int y = 0; y < recthei; y++)
{
for (int x = 0; x < rectwid; x++)
{
int index = y * rectwid + x;
Color ocol = ocols[index];
Color gcol = gcols[index];
float k = alpha * gcol.a;
ocols[index] = BlendColor(ocol, gcol, k);
}
}
tex.SetPixels(left, bottom, rectwid, recthei, ocols);
tex.Apply();
}
}
}
if (Input.GetMouseButtonUp(0))
{
StopSpray();
}
}
private void StartSpray(Transform obj)
{
isStart = true;
mat = obj.GetComponent<MeshRenderer>().sharedMaterial;
tex = (Texture2D)mat.GetTexture("_MainTex");
texWidth = tex.width;
texHeight = tex.height;
}
private void StopSpray()
{
isStart = false;
}
private Color BlendColor(Color a, Color b, float k)
{
Color c = Color.Lerp(a, b, k);
return c;
}
}
The core is based on drawing rect Just mix the sampling pattern with the background color array , The effect is as follows : Pay special attention to rectangles “ breakthrough ” The problem of pattern sampling coordinates in the case of boundary .
Of course, there are still many problems that need to be solved , such as :
1. Model UV joint 、 How to deal with the joint spraying between models ?
2. spraying + Grid computing works together , similar zbrush operation ?
3. Can we handle it? 3d Texture matching model coloring ?
Later, there is time to slowly realize .
by the way , By the way , This kind of drawing operation is not suitable for use ComputeShader, I wrote a test , although ComputeShader In the calculation of color matrix CPU fast , But on the data bus bus The exchange is too time-consuming , Not suitable for this spraying operation .
边栏推荐
- All metal crowns - current market situation and future development trend
- What is the student party's Bluetooth headset recommendation? Student party easy to use Bluetooth headset recommended
- Use classname to modify style properties
- When tidb meets Flink: tidb efficiently enters the lake "new play" | tilaker team interview
- Mongodb learning notes: command line tools
- Infiltration learning diary day19
- The latest analysis of hoisting machinery command in 2022 and free examination questions of hoisting machinery command
- Maximum likelihood method, likelihood function and log likelihood function
- 1189. Maximum number of "balloons"
- Skku| autonomous handover decision of UAV Based on deep reinforcement learning
猜你喜欢
Basic editing specifications and variables of shell script
Jerry's modification setting status [chapter]
Audio resource settings for U3D resource management
Huawei BFD and NQA
Meta metauniverse female safety problems occur frequently, how to solve the relevant problems in the metauniverse?
Yyds dry goods inventory it's not easy to say I love you | use the minimum web API to upload files
Introduction to superresolution
Rearrangement of tag number of cadence OrCAD components and sequence number of schematic page
Three layer switching ①
Applet graduation project is based on wechat classroom laboratory reservation applet graduation project opening report function reference
随机推荐
Is Shengang securities company as safe as other securities companies
mysql使用視圖報錯,EXPLAIN/SHOW can not be issued; lacking privileges for underlying table
Skku| autonomous handover decision of UAV Based on deep reinforcement learning
The difference between lambda expressions and anonymous inner classes
Long article review: entropy, free energy, symmetry and dynamics in the brain
C import Xls data method summary I (upload files and create Workbooks)
How to view the computing power of GPU?
Small program graduation project based on wechat e-book small program graduation project opening report function reference
2020-12-02 SSM advanced integration Shang Silicon Valley
CLP information - how does the digital transformation of credit business change from star to finger?
Decompile and modify the non source exe or DLL with dnspy
2022 new examination questions for safety management personnel of hazardous chemical business units and certificate examination for safety management personnel of hazardous chemical business units
Remember a lazy query error
Small program graduation design is based on wechat order takeout small program graduation design opening report function reference
Conditional statements of shell programming
Why can't it run (unresolved)
JVM performance tuning and practical basic theory - medium
String hash, find the string hash value after deleting any character, double hash
When tidb meets Flink: tidb efficiently enters the lake "new play" | tilaker team interview
Do you know the eight signs of a team becoming agile?