我正在尝试在片段着色器中获取像素的世界位置。
让我解释一下。我遵循一个教程,使用分段着色器在对象上绘制图案。现在它通过纹理坐标工作,但我希望它能够通过像素的世界位置工作。因此,当我单击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模型,随着绘画进入另一侧,应该在渲染纹理的各个地方都有颜色...但现在只有一条线从顶部到底部的纹理。当我尝试在对象的下半部分绘画时,渲染纹理上什么也没有显示。只有当我在上半部分绘画时,才能看到红色的线条(默认的绘画颜色)。
如果您愿意,可以在此处下载示例项目。
以下是我正在使用的代码。
Draw.shader
我尝试解决这个问题的方法是这样的。我在谷歌上搜索了这个线程所涉及的问题,并尝试在我的项目中进行实现。我还发现了一些具有我需要功能的项目,比如这一个网格纹理绘制。这个项目完全符合我的需求,但在iOS上不起作用。3D对象会变成黑色。您可以查看我之前发布的帖子来解决问题,并在Twitter上与创建者交流,但他无法帮助我。此外,我尝试了这个工具,它运行时fps非常低,很难为我的需求进行定制,而且不能在我的3D模型边缘上绘制。
那个工作良好的着色器很简单,所以我可以更改它并得到期望的效果。
谢谢!
让我解释一下。我遵循一个教程,使用分段着色器在对象上绘制图案。现在它通过纹理坐标工作,但我希望它能够通过像素的世界位置工作。因此,当我单击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模型,随着绘画进入另一侧,应该在渲染纹理的各个地方都有颜色...但现在只有一条线从顶部到底部的纹理。当我尝试在对象的下半部分绘画时,渲染纹理上什么也没有显示。只有当我在上半部分绘画时,才能看到红色的线条(默认的绘画颜色)。
如果您愿意,可以在此处下载示例项目。
以下是我正在使用的代码。
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);
}
}
}
}
那个工作良好的着色器很简单,所以我可以更改它并得到期望的效果。
谢谢!