只是想知道是否有人可以伸出援手,到目前为止花了好几个小时:
有谁知道为什么会这样?随着我的移动,底部总是比顶部更亮。
vert的基本流程: *获得+ X点和+ Z点,以便稍后用于交叉乘法以获得正常
*将这些点转换为世界空间,以便我可以在现实空间中寻找障碍物
*计算出我们的点的y轴位移+第一步中为交叉
制作的额外内容*按位移增加对象空间值
*使用交叉
找到新常态*设置正常
*设置顶点。
我认为正在发生的是法线在错误的轴上......任何帮助都会出现
Shader "Custom/ExtrudePointArray" {
Properties {
_Color ("Color", Color) = (1,1,1,1)
_MainTex ("Albedo (RGB)", 2D) = "white" {}
_Glossiness("Smoothness", Range(0,1)) = 0.5
_Metallic("Metallic", Range(0,1)) = 0.0
//water stuff
_Scale("Scale", float) = 1
_Speed("Speed", float) = 1
_Frequency("Frequency", float) = 1
// wave maker
_Height("_Height", float) = 1.0
_Extrude_Close("_Extrude_Close", float) = 3.0
[HideInInspector]_ExtrudePointCount("_ExtrudePointCount", int) = 0
}
SubShader {
Tags { "RenderType"="Opaque" }
LOD 200
CGPROGRAM
// Physically based Standard lighting model, and enable shadows on all light types
#pragma surface surf Standard fullforwardshadows vertex:vert
//debug normals
//#pragma surface surf Standard fullforwardshadows vertex:vert finalcolor:showNormals
// Use shader model 3.0 target, to get nicer looking lighting
#pragma target 4.0
sampler2D _MainTex;
struct Input {
float2 uv_MainTex;
float3 newNormal;
half3 debugColor;
};
half _Glossiness;
half _Metallic;
fixed4 _Color;
// water stuff
float _Scale, _Speed, _Frequency;
float _Extrude_Close, _Height;
uniform float _ExtrudePointX[20], _ExtrudePointZ[20], _ExtrudePointCount;
float calcWaveHeight(float2 worvldLoc) {
//disruption
half offsetvertDis = ((worvldLoc.x * worvldLoc.x) + (worvldLoc.y * worvldLoc.y));
half valueDis = _Scale * sin(_Time.w * _Speed + offsetvertDis * _Frequency*1000);
// diag wave
half offsetvertDiag = worvldLoc.x +worvldLoc.y;
half valueDiag = _Scale * sin(_Time.w * _Speed * _Frequency + offsetvertDiag);
return valueDis + valueDiag;
}
float calcDistFromPoint(float2 worldLoc, float2 pointToCheck) {
float closePercent = 0;
float dist = abs(distance(worldLoc, pointToCheck));
if (dist < _Extrude_Close) {
closePercent = (_Extrude_Close - dist / _Extrude_Close);
}
return closePercent;
}
float calcVertNewPos(float3 worldLoc) {
float highestPos = 0;
float2 worldLocHor = float2(worldLoc.x, worldLoc.z);
for (int i = 0; i < _ExtrudePointCount; i++) {
float2 boxPos = float2(_ExtrudePointX[i], _ExtrudePointZ[i]);
float newPos = calcDistFromPoint(worldLocHor, boxPos) * _Height;
// the value returned is a float so don't check for zero, check that it's not above zero
if (newPos < 0.001) {
newPos = calcWaveHeight(worldLocHor);
}
if (newPos > highestPos) {
highestPos = newPos;
}
//highestPos = worldLoc.x * i;
}
return highestPos;
}
void vert(inout appdata_full v, out Input o)
{
UNITY_INITIALIZE_OUTPUT(Input, o);
float3 v0 = v.vertex.xyz;
float3 v1 = v0 + float3(0.05, 0, 0); // +X
float3 v2 = v0 + float3(0, 0, 0.05); // +Z
float3 w0 = mul(unity_ObjectToWorld, v.vertex).xyz;
float3 w1 = w0 + float3(0.05, 0, 0); // +X
float3 w2 = w0 + float3(0, 0, 0.05); // +Z
float h0 = calcVertNewPos(w0);
float h1 = calcVertNewPos(w1);
float h2 = calcVertNewPos(w2);
v0.y = h0;
v1.y = h1;
v2.y = h2;
float3 vna = cross(v2 - v0, v1 - v0);
// debug
//o.debugColor = (normalize(v0) * 0.5) + 0.5;
//o.debugColor = (normalize(v.vertex.xyz) * 0.5) + 0.5;
//o.debugColor = (normalize(vna) * 0.5) + 0.5;
// Put normals back in object space
//float3x3 worlspace = float3x3(unity_WorldToObject.xyz);
v.normal = normalize(vna);
o.newNormal = v.normal;
v.vertex.xyz = v0;
}
void showNormals(Input IN, SurfaceOutputStandard o, inout fixed4 color) {
color.rgb = IN.debugColor.rgb;
color.a = 1;
}
void surf (Input IN, inout SurfaceOutputStandard o) {
// Albedo comes from a texture tinted by color
fixed4 c = tex2D (_MainTex, IN.uv_MainTex) * _Color;
o.Albedo = c.rgb;
// Metallic and smoothness come from slider variables
o.Metallic = _Metallic;
o.Smoothness = _Glossiness;
o.Alpha = c.a;
o.Normal = IN.newNormal;
}
ENDCG
}
FallBack "Diffuse"
}
我知道我几乎肯定会做出错误的判断正常计算。但是我找不到任何好的资源而且我找到了唯一的东西:https://www.youtube.com/watch?v=1G37-Yav2ZM是为了早期版本的着色器语言和下载源的网站现在是恶意软件:(这是杀了我
此处还有运行着色器挤出点的代码(如果需要):
using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class ExtrudePoint : MonoBehaviour {
public GameObject[] Waves;
private Renderer _renderer;
// Use this for initialization
void Start()
{
if (Waves == null || Waves.Length > 8)
{
throw new Exception("Max of 8 waves, min of 1");
}
_renderer = GetComponent<Renderer>();
}
// Update is called once per frame
void Update()
{
int totWaves = 0;
// probably slow
var floatArrayX = new float[Waves.Length];
var floatArrayZ = new float[Waves.Length];
for (var i = 0; i < Waves.Length; i++)
{
var wave = Waves[i];
if (wave != null)
{
totWaves++;
floatArrayX[totWaves - 1] = wave.gameObject.transform.position.x;
floatArrayZ[totWaves - 1] = wave.gameObject.transform.position.z;
//_renderer.material.SetFloat(WavePointExtruderConstants._ExtrudePointX, wave.gameObject.transform.position.x);
//_renderer.material.SetFloat(WavePointExtruderConstants._ExtrudePointZ, wave.gameObject.transform.position.z);
//Debug.Log(wave.gameObject.transform.position);
}
}
// probably slow
var xWaveArray = new float[totWaves];
var zWaveArray = new float[totWaves];
for(int i = 0; i < totWaves; i++)
{
xWaveArray[i] = floatArrayX[i];
zWaveArray[i] = floatArrayZ[i];
}
//Debug.Log(totWaves);
_renderer.material.SetFloatArray(WavePointExtruderConstants._ExtrudePointX, xWaveArray);
_renderer.material.SetFloatArray(WavePointExtruderConstants._ExtrudePointZ, zWaveArray);
_renderer.material.SetFloat(WavePointExtruderConstants._ExtrudePointCount, totWaves);
}
}
public static class WavePointExtruderConstants
{
public static string _Extrude_Close = "_Extrude_Close";
public static string _ExtrudePointX = "_ExtrudePointX";
public static string _ExtrudePointZ = "_ExtrudePointZ";
public static string _ExtrudePointCount = "_ExtrudePointCount";
}
设置是一个平面,上面有着色器材质+代码。然后你制作任何游戏对象并将其放入Waves数组的脚本中。
答案 0 :(得分:1)
着色器中至少有两个问题。
首先,当你在表面着色器中执行o.Normal = myNormal;
时,myNormal应该在切线空间中,但是着色器正在传递在世界空间中计算的法线< /强>
所以这里有一个解决方案(从世界空间转换为切线空间的统一特定代码):
//---- before
//v.normal = normalize(vna);
//o.newNormal = v.normal;
//--- after
float3 worldNormal = normalize(vna);
// unity macro which setups "world space->tangent space" matrix in "rotation" variable
TANGENT_SPACE_ROTATION;
float3 tangentSpaceNormal = mul(rotation, worldNormal);
o.newNormal = tangentSpaceNormal;
其次,您使用的代码计算顶点的法线实际上是计算由(v0,v1,v2)定义的多边形/面法线的代码),这并非完全错误,但可能无法按预期工作。
计算顶点V法线的好方法是:
这里使用平面网格,因此每个面都是四边形,每个顶点属于4个四边形(对于边界顶点不是真的,但在你的情况下这不是问题)。
所以你当前的代码在X&amp;中加了+0.05 Z实际上是计算顶点右上角的四边形/面的法线(如果您使用Unity顶视图的原因)。
所以为了获得良好的法线,你需要计算3个其他四边形/面的法线,这将给你4个法线,最后通过平均那些你将得到顶点法线(将它们相加并除以4) )。