请帮我用unity 实现 再RenderTexture上画线的shader ,要求线有头尾效果,可橡皮擦,写出测试代码
时间: 2024-03-14 18:47:38 浏览: 56
以下是实现在RenderTexture上画线的Shader,并且具有头尾效果和橡皮擦功能的代码:
```
Shader "Custom/LineShader"
{
Properties
{
_Color ("Color", Color) = (1,1,1,1)
_Thickness ("Thickness", Range(0.01, 0.1)) = 0.05
_Erase ("Erase", Range(0,1)) = 0
_MainTex ("Texture", 2D) = "white" {}
}
SubShader
{
Tags {"Queue"="Transparent" "RenderType"="Opaque"}
LOD 100
Pass
{
CGPROGRAM
#pragma vertex vert
#pragma fragment frag
#include "UnityCG.cginc"
struct appdata_t
{
float4 vertex : POSITION;
float2 uv : TEXCOORD0;
};
struct v2f
{
float2 uv : TEXCOORD0;
float4 vertex : SV_POSITION;
};
sampler2D _MainTex;
float4 _MainTex_ST;
float4 _Color;
float _Thickness;
float _Erase;
v2f vert (appdata_t v)
{
v2f o;
o.vertex = UnityObjectToClipPos(v.vertex);
o.uv = TRANSFORM_TEX(v.uv, _MainTex);
return o;
}
fixed4 frag (v2f i) : SV_Target
{
float4 col = tex2D(_MainTex, i.uv) * _Color;
if (_Erase == 1) col = float4(0,0,0,0);
// 计算线条的宽度
float2 delta = float2(ddx(i.uv.x), ddy(i.uv.y)) * _ScreenParams.zw * _Thickness;
float2 line = float2(1,1) - saturate(abs(i.uv - 0.5) * 2 - delta);
col *= line.x * line.y;
// 计算线头和线尾
float2 head = saturate(i.uv * 20) * saturate((i.uv - 0.95) * 20);
float2 tail = saturate((1 - i.uv) * 20) * saturate((0.05 - i.uv) * 20);
col *= pow(head.x * head.y + tail.x * tail.y, 2.0);
return col;
}
ENDCG
}
}
}
```
测试代码:
```
using UnityEngine;
using System.Collections;
public class DrawOnRenderTexture : MonoBehaviour {
public Shader lineShader;
public Color color = Color.white;
public float thickness = 0.05f;
public bool erase = false;
private RenderTexture renderTexture;
private Material lineMaterial;
private Vector2? lastPoint = null;
void Start () {
// 创建一个256x256的RenderTexture
renderTexture = new RenderTexture(256, 256, 0);
renderTexture.Create();
// 创建一个材质球,并将Shader设置为我们自定义的LineShader
lineMaterial = new Material(lineShader);
lineMaterial.SetTexture("_MainTex", renderTexture);
lineMaterial.SetColor("_Color", color);
lineMaterial.SetFloat("_Thickness", thickness);
lineMaterial.SetFloat("_Erase", erase ? 1 : 0);
}
void Update () {
// 当鼠标左键按下时,开始绘制
if (Input.GetMouseButtonDown(0)) {
lastPoint = Input.mousePosition;
}
// 当鼠标左键抬起时,停止绘制
if (Input.GetMouseButtonUp(0)) {
lastPoint = null;
}
// 当鼠标左键按下且移动时,绘制线条
if (Input.GetMouseButton(0)) {
if (lastPoint.HasValue) {
// 计算线条的起点和终点
Vector2 startPoint = lastPoint.Value / Screen.width;
Vector2 endPoint = Input.mousePosition / Screen.width;
// 在RenderTexture上绘制线条
RenderTexture.active = renderTexture;
GL.Clear(true, true, Color.clear);
GL.PushMatrix();
lineMaterial.SetPass(0);
GL.LoadOrtho();
GL.Begin(GL.QUADS);
GL.TexCoord2(0, 0); GL.Vertex3(startPoint.x, startPoint.y, 0);
GL.TexCoord2(0, 1); GL.Vertex3(startPoint.x, endPoint.y, 0);
GL.TexCoord2(1, 1); GL.Vertex3(endPoint.x, endPoint.y, 0);
GL.TexCoord2(1, 0); GL.Vertex3(endPoint.x, startPoint.y, 0);
GL.End();
GL.PopMatrix();
RenderTexture.active = null;
// 更新起点
lastPoint = endPoint * Screen.width;
}
}
}
void OnGUI () {
// 在屏幕上显示RenderTexture的内容
GUI.DrawTexture(new Rect(0, 0, Screen.width, Screen.height), renderTexture, ScaleMode.ScaleToFit, false, 0);
}
}
```
这个代码会在屏幕上创建一个256x256的RenderTexture,并且绑定到材质球上。当鼠标左键按下并移动时,会在RenderTexture上绘制线条,并且在屏幕上显示RenderTexture的内容。通过修改Shader的参数,可以实现不同的线条效果。
阅读全文