【发布时间】:2020-06-18 11:57:44
【问题描述】:
我正在尝试获取碎片着色器中像素的世界位置。
让我解释一下。我关注了tutorial 的碎片着色器,让我可以在对象上绘画。现在它通过纹理坐标工作,但我希望它通过像素的世界位置工作。因此,当我单击 3D 模型以便能够将 Vector3 位置(单击发生的位置)与像素 Vector3 位置进行比较时,以及距离是否足够小以影响颜色。
这是我的设置。我创建了一个新的 3D 项目,只是为了制作着色器,以便稍后将其导出到我的主项目中。在场景中,我有默认的主摄像头、定向光、一个带有脚本的对象,该脚本向我显示 fps 和一个带有网格碰撞器的默认 3D 立方体。我创建了一个新材质和一个新的标准曲面着色器并将其添加到立方体中。之后,我将下一个 C# 脚本分配给带有着色器和相机参考的立方体。
更新:现在的问题是 blit 没有按预期工作。如果按照 Kalle 所说的更改着色器脚本,从 c# 脚本中删除 blit,并将着色器从 3D 模型材质更改为 Draw 着色器,它将按预期工作,但没有任何光照。出于我的目的,我不得不将 distance(_Mouse.xyz, i.worldPos.xyz); 更改为 distance(_Mouse.xz, i.worldPos.xz); 所以它会一直画到另一边。为了调试,我创建了一个 RenderTexture,每一帧我都使用 Blit 来更新纹理并查看发生了什么。当对象着色时,渲染纹理没有保持正确的位置。我拥有的 3D 模型有很多几何形状,当油漆移到另一边时,它应该遍布渲染纹理的所有位置……但现在它只是从纹理的顶部到底部在线。此外,我尝试在对象的下半部分进行绘制,渲染纹理没有显示任何内容。只有当我在上半部分绘画时,我才能看到红线(默认绘画颜色)。
如果需要,可以下载示例项目here。
这是我正在使用的代码。
Draw.shader
Shader "Unlit/Draw"
{
Properties
{
_MainTex ("Texture", 2D) = "white" {}
_Coordinate("Coordinate",Vector)=(0,0,0,0)
_Color("Paint Color",Color)=(1,1,1,1)
}
SubShader
{
Tags { "RenderType"="Opaque" }
LOD 100
Pass
{
CGPROGRAM
#pragma vertex vert
#pragma fragment frag
#include "UnityCG.cginc"
struct appdata
{
float4 vertex : POSITION;
float2 uv : TEXCOORD0;
};
struct v2f
{
float2 uv : TEXCOORD0;
float4 vertex : SV_POSITION;
};
sampler2D _MainTex;
float4 _MainTex_ST;
fixed4 _Coordinate,_Color;
v2f vert (appdata v)
{
v2f o;
o.vertex = UnityObjectToClipPos(v.vertex);
o.uv = TRANSFORM_TEX(v.uv, _MainTex);
return o;
}
fixed4 frag (v2f i) : SV_Target
{
// sample the texture
fixed4 col = tex2D(_MainTex, i.uv);
float draw =pow(saturate(1-distance(i.uv,_Coordinate.xy)),100);
fixed4 drawcol = _Color * (draw * 1);
return saturate(col + drawcol);
}
ENDCG
}
}
}
Draw.cs
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class Draw : MonoBehaviour
{
public Camera cam;
public Shader paintShader;
RenderTexture splatMap;
Material snowMaterial,drawMaterial;
RaycastHit hit;
private void Awake()
{
Application.targetFrameRate = 200;
}
void Start()
{
drawMaterial = new Material(paintShader);
drawMaterial.SetVector("_Color", Color.red);
snowMaterial = GetComponent<MeshRenderer>().material;
splatMap = new RenderTexture(1024, 1024, 0, RenderTextureFormat.ARGBFloat);
snowMaterial.mainTexture = splatMap;
}
void Update()
{
if (Input.GetMouseButton(0))
{
if(Physics.Raycast(cam.ScreenPointToRay(Input.mousePosition),out hit))
{
drawMaterial.SetVector("_Coordinate", new Vector4(hit.textureCoord.x, hit.textureCoord.y, 0, 0));
RenderTexture temp = RenderTexture.GetTemporary(splatMap.width, splatMap.height, 0, RenderTextureFormat.ARGBFloat);
Graphics.Blit(splatMap, temp);
Graphics.Blit(temp, splatMap, drawMaterial);
RenderTexture.ReleaseTemporary(temp);
}
}
}
}
至于我试图解决的问题是这样的。我在谷歌上搜索了这个线程的问题,并试图在我的项目中实现它。我还发现了一些具有我需要的功能的项目,例如Mesh Texuture Painting。这个完全符合我的需要,但它不适用于 iOS。 3D 对象变为黑色。你可以查看previous post我为解决问题而设计的,也可以在 Twitter 上与创建者交谈,但他无法帮助我。我也尝试过this asset,它工作正常,但在我的主项目中运行的 fps 非常低,我很难根据自己的需要自定义它,而且它不会在我的 3D 模型的边缘上绘制。
效果很好的着色器很简单,所以我可以更改它并获得所需的效果就是上面的那个。
谢谢!
【问题讨论】:
标签: unity3d 3d shader textures paint