我用Blender中的节点编辑器模拟了一个着色器。现在我试着用HLSL编写它。在Blender中有一个名为“纹理坐标”的节点组。如果我使用组中的" uv“节点,它的行为就像一个普通的未光照的框架着色器,但是如果我使用" object”节点给出纹理的坐标,它就会忽略uv数据,而只是像一幅叠加在物体上的图像一样映射纹理。
这就是我想要的效果。但是,我无法找到在HLSL中复制这一功能的方法。据我所见,我可以使用TEXCOORD0
和POSITION
作为纹理坐标,分别为对象上的纹理生成uv映射和世界映射。也许我想要的是对象映射?
如果有关系的话,我用的是生成的纹理
发布于 2019-02-13 10:25:47
纹理坐标节点通常用于纹理的坐标,通常用作纹理节点的矢量输入的输入。
Shader "Blender/ObjectNode"
{
SubShader
{
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;
float4 worldPos : TEXCOORD2;
};
float4 _Pos;
v2f vert (appdata v)
{
v2f o;
o.vertex = UnityObjectToClipPos(v.vertex);
o.worldPos = mul(unity_ObjectToWorld, v.vertex);
o.uv = v.uv;
return o;
}
sampler2D _MainTex;
fixed4 frag (v2f i) : SV_Target
{
return i.worldPos;
}
ENDCG
}
}
}
您可以通过从-1,1到1,0的世界位置来实现生成节点。
Shader "Blender/GeneratedNode"
{
SubShader
{
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;
float4 worldPos : TEXCOORD2;
};
float4 _Pos;
v2f vert (appdata v)
{
v2f o;
o.vertex = UnityObjectToClipPos(v.vertex);
o.worldPos = mul(unity_ObjectToWorld, v.vertex);
o.uv = v.uv;
return o;
}
sampler2D _MainTex;
fixed4 frag (v2f i) : SV_Target
{
return i.worldPos*0.5+0.5;
}
ENDCG
}
}
}
重新映射是扩展坐标的一种方法:
现在,当我们在搅拌器中移动对象时,我们得到了这样的结果:
但是,在团结中,我们没有相同的结果:
我们应该重新定位来解决这个问题:
Shader "Blender/ObjectNode"
{
Properties
{
_Pos("Pos",Vector) = (0,0,0,0)
}
SubShader
{
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;
float4 worldPos : TEXCOORD2;
};
float4 _Pos;
v2f vert (appdata v)
{
v2f o;
o.vertex = UnityObjectToClipPos(v.vertex);
o.worldPos = mul(unity_ObjectToWorld, v.vertex-_Pos);
o.uv = v.uv;
return o;
}
sampler2D _MainTex;
fixed4 frag (v2f i) : SV_Target
{
return i.worldPos;
}
ENDCG
}
}
}
然后将此脚本附加到对象以更新位置:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
[ExecuteInEditMode]
public class ResetPos : MonoBehaviour {
void Update () {
GetComponent<MeshRenderer>().material.SetVector("_Pos",transform.position);
}
}
ObjectNode
Shader "ObjectNode" {
Properties {
}
SubShader {
Tags { "RenderType"="Opaque" }
LOD 200
CGPROGRAM
#pragma surface surf Lambert vertex:vert
struct Input {
float3 objPos;
};
void vert (inout appdata_full v, out Input o) {
UNITY_INITIALIZE_OUTPUT(Input,o);
o.objPos = v.vertex;
}
void surf (Input IN, inout SurfaceOutput o) {
o.Albedo = IN.objPos;
o.Alpha = 1;
}
ENDCG
}
}
GeneratedNode
Shader "GeneratedNode" {
Properties {
}
SubShader {
Tags { "RenderType"="Opaque" }
LOD 200
CGPROGRAM
#pragma surface surf Lambert vertex:vert
struct Input {
float3 objPos;
};
void vert (inout appdata_full v, out Input o) {
UNITY_INITIALIZE_OUTPUT(Input,o);
o.objPos = v.vertex;
}
void surf (Input IN, inout SurfaceOutput o) {
o.Albedo = IN.objPos*0.5+0.5;
o.Alpha = 1;
}
ENDCG
}
}
https://gamedev.stackexchange.com/questions/168018
复制相似问题