Unityの新しいPostProcessingシェーダーフレームワークの1つは、問題のピクセルの絶対xyzワールド位置をどのように取得しますか?どうもありがとう!
Shader "Hidden/Filter/Test" {
HLSLINCLUDE
#include "../../PostProcessing/Shaders/StdLib.hlsl"
TEXTURE2D_SAMPLER2D(_MainTex, sampler_MainTex);
float4 Frag(VaryingsDefault i) : SV_Target {
float4 color = SAMPLE_TEXTURE2D(_MainTex, sampler_MainTex, i.texcoordStereo);
// what's the world position of this color pixel ...?
return color;
}
ENDHLSL
SubShader {
Cull Off ZWrite Off ZTest Always
Pass {
HLSLPROGRAM
#pragma vertex VertDefault
#pragma fragment Frag
ENDHLSL
}
}
}
Leceはあなたのコメントで正しく言った:
"UnityCG.cginc"
マクロへのアクセスを含むほとんどの組み込み機能に必要な#includeUNITY_*
がありません。
しかし、問題は、"UnityCG.cginc"
PostProcessingスタック2を使用する場合、Unityの組み込みシェーダーで同じ関数と競合するため、標準のシェーダーユニティで見つけることにしました。
nity Archiveシェーダー でUNITY_MATRIX_MVP
をStandard\CGIncludes\UnityShaderVariables.cginc
で見つけることができます
#define UNITY_MATRIX_MVP mul(unity_MatrixVP, unity_ObjectToWorld)
Shader "Hidden/Filter/Test" {
HLSLINCLUDE
#include "../../PostProcessing/Shaders/StdLib.hlsl"
#define UNITY_MATRIX_MVP mul(unity_MatrixVP, unity_ObjectToWorld)
TEXTURE2D_SAMPLER2D(_MainTex, sampler_MainTex);
struct v2f {
float4 vertex : SV_POSITION;
float3 worldPos : TEXCOORD0;
float2 texcoord : TEXCOORD1;
float2 texcoordStereo : TEXCOORD2;
};
struct appdata {
float4 vertex : POSITION;
};
v2f VertDefault(appdata v) {
v2f o;
o.worldPos = mul (unity_ObjectToWorld, v.vertex);
o.vertex = float4(v.vertex.xy, 0.0, 1.0);
o.texcoord = TransformTriangleVertexToUV(v.vertex.xy);
#if UNITY_UV_STARTS_AT_TOP
o.texcoord = o.texcoord * float2(1.0, -1.0) + float2(0.0, 1.0);
#endif
o.texcoordStereo = TransformStereoScreenSpaceTex(o.texcoord, 1.0);
return o;
}
float4 Frag(v2f i) : SV_Target {
float worldPos = i.worldPos;
float4 color = SAMPLE_TEXTURE2D(_MainTex, sampler_MainTex, i.texcoordStereo);
return float4(i.worldPos,1);
}
ENDHLSL
SubShader {
Cull Off ZWrite Off ZTest Always
Pass {
HLSLPROGRAM
#pragma vertex VertDefault
#pragma fragment Frag
ENDHLSL
}
}
}
また、worldposをStdLib.hlsl
に追加することもできます。これは、PostProcessing-2\Assets\PostProcessing\Shaders
で見つけることができ、次の行を変更します。
StdLib.hlsl
を修正し、 ここ
#define UNITY_MATRIX_MVP mul(unity_MatrixVP, unity_ObjectToWorld)
struct VaryingsDefault
{
float4 vertex : SV_POSITION;
float2 texcoord : TEXCOORD0;
float2 texcoordStereo : TEXCOORD1;
float3 worldPos : TEXCOORD2;
};
VaryingsDefault VertDefault(AttributesDefault v)
{
VaryingsDefault o;
o.vertex = float4(v.vertex.xy, 0.0, 1.0);
o.texcoord = TransformTriangleVertexToUV(v.vertex.xy);
o.worldPos = mul (unity_ObjectToWorld, v.vertex);
#if UNITY_UV_STARTS_AT_TOP
o.texcoord = o.texcoord * float2(1.0, -1.0) + float2(0.0, 1.0);
#endif
o.texcoordStereo = TransformStereoScreenSpaceTex(o.texcoord, 1.0);
return o;
}
このようにワールドスペースの使用は簡単です!
Shader "Hidden/Filter/Test" {
HLSLINCLUDE
#include "../../PostProcessing/Shaders/StdLib.hlsl"
float4 Frag(VaryingsDefault i) : SV_Target {
return float4(i.worldPos,1);//Using World Position!
}
ENDHLSL
SubShader {
Cull Off ZWrite Off ZTest Always
Pass {
HLSLPROGRAM
#pragma vertex VertDefault
#pragma fragment Frag
ENDHLSL
}
}
}
https://www.youtube.com/watch?v=uMOOcmp6FrM
このスクリプトをカメラに添付します。
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class DepthBuffToWorldPosDemo : MonoBehaviour
{
public Material material;
private new Camera camera;
private new Transform transform;
private void Start()
{
camera = GetComponent<Camera>();
transform = GetComponent<Transform>();
}
void OnRenderImage(RenderTexture source, RenderTexture destination)
{
// NOTE: code was ported from: https://gamedev.stackexchange.com/questions/131978/shader-reconstructing-position-from-depth-in-vr-through-projection-matrix
var p = GL.GetGPUProjectionMatrix(camera.projectionMatrix, false);
p[2, 3] = p[3, 2] = 0.0f;
p[3, 3] = 1.0f;
var clipToWorld = Matrix4x4.Inverse(p * camera.worldToCameraMatrix) * Matrix4x4.TRS(new Vector3(0, 0, -p[2,2]), Quaternion.identity, Vector3.one);
material.SetMatrix("clipToWorld", clipToWorld);
Graphics.Blit(source, destination, material);
}
}
unityシェーダーまたは後処理シェーダーを使用できます
Unityシェーダー:
Shader "Hidden/DepthBuffToWorldPos"
{
SubShader
{
Cull Off ZWrite Off ZTest Always
Pass
{
CGPROGRAM
#pragma vertex vert
#pragma fragment frag
#pragma target 5.0
#include "UnityCG.cginc"
struct appdata
{
float4 vertex : POSITION;
float2 uv : TEXCOORD0;
};
struct v2f
{
float2 uv : TEXCOORD0;
float3 worldDirection : TEXCOORD1;
float4 vertex : SV_POSITION;
};
float4x4 clipToWorld;
v2f vert (appdata v)
{
v2f o;
o.vertex = UnityObjectToClipPos(v.vertex);
o.uv = v.uv;
float4 clip = float4(o.vertex.xy, 0.0, 1.0);
o.worldDirection = mul(clipToWorld, clip) - _WorldSpaceCameraPos;
return o;
}
sampler2D_float _CameraDepthTexture;
float4 _CameraDepthTexture_ST;
float4 frag (v2f i) : SV_Target
{
float depth = SAMPLE_DEPTH_TEXTURE(_CameraDepthTexture, i.uv.xy);
depth = LinearEyeDepth(depth);
float3 worldspace = i.worldDirection * depth + _WorldSpaceCameraPos;
float4 color = float4(worldspace, 1.0);
return color;
}
ENDCG
}
}
}
後処理スタックシェーダー
Shader "Hidden/Filter/Test" {
HLSLINCLUDE
#include "../../PostProcessing/Shaders/StdLib.hlsl"
#define UNITY_MATRIX_MVP mul(unity_MatrixVP, unity_ObjectToWorld)
#include "HLSLSupport.cginc"
#pragma fragmentoption ARB_precision_hint_nicest
TEXTURE2D_SAMPLER2D(_MainTex, sampler_MainTex);
float4x4 clipToWorld;
struct v2f {
float4 vertex : SV_POSITION;
float3 worldDirection : TEXCOORD0;
float3 screenPos : TEXCOORD1;
float2 texcoord : TEXCOORD2;
float2 texcoordStereo : TEXCOORD3;
};
struct appdata {
float4 vertex : POSITION;
};
sampler2D_float _CameraDepthTexture;
float4 _CameraDepthTexture_ST;
v2f VertDefault(appdata v) {
v2f o;
o.vertex = float4(v.vertex.xy, 0.0, 1.0);
o.texcoord = TransformTriangleVertexToUV(v.vertex.xy);
float4 clip = float4(o.vertex.xy, 0.0, 1.0);
o.worldDirection = mul(clipToWorld, clip) - _WorldSpaceCameraPos;
#if UNITY_UV_STARTS_AT_TOP
o.texcoord = o.texcoord * float2(1.0, -1.0) + float2(0.0, 1.0);
#endif
// Correct flip when rendering with a flipped projection matrix.
// (I've observed this differing between the Unity scene & game views)
o.screenPos.y *= _ProjectionParams.x;
o.vertex = mul(UNITY_MATRIX_MVP, v.vertex);
o.screenPos = o.vertex.xyw;
o.texcoordStereo = TransformStereoScreenSpaceTex(o.texcoord, 1.0);
return o;
}
float4 Frag(v2f i) : SV_Target {
float2 screenUV = (i.screenPos.xy / i.screenPos.z) * 0.5f + 0.5f;
float depth = SAMPLE_DEPTH_TEXTURE(_CameraDepthTexture,screenUV);
depth = LinearEyeDepth(depth);
float3 worldspace = i.worldDirection * depth + _WorldSpaceCameraPos;
float4 color = float4(worldspace, 1.0);
return color;
}
ENDHLSL
SubShader {
Cull Off ZWrite Off ZTest Always
Pass {
HLSLPROGRAM
#pragma vertex VertDefault
#pragma fragment Frag
ENDHLSL
}
}
}
#define UNITY_MATRIX_MVP mul(unity_MatrixVP, unity_ObjectToWorld)
#include "HLSLSupport.cginc"
#pragma fragmentoption ARB_precision_hint_nicest
float4x4 clipToWorld;
struct VaryingsDefault
{
float4 vertex : SV_POSITION;
float3 worldDirection : TEXCOORD0;
float3 screenPos : TEXCOORD1;
float2 texcoord : TEXCOORD2;
float2 texcoordStereo : TEXCOORD3;
};
sampler2D_float _CameraDepthTexture;
float4 _CameraDepthTexture_ST;
VaryingsDefault VertDefault(AttributesDefault v)
{
VaryingsDefault o;
o.vertex = float4(v.vertex.xy, 0.0, 1.0);
o.texcoord = TransformTriangleVertexToUV(v.vertex.xy);
float4 clip = float4(o.vertex.xy, 0.0, 1.0);
o.worldDirection = mul(clipToWorld, clip) - _WorldSpaceCameraPos;
#if UNITY_UV_STARTS_AT_TOP
o.texcoord = o.texcoord * float2(1.0, -1.0) + float2(0.0, 1.0);
#endif
// Correct flip when rendering with a flipped projection matrix.
// (I've observed this differing between the Unity scene & game views)
o.screenPos.y *= _ProjectionParams.x;
o.vertex = mul(UNITY_MATRIX_MVP, v.vertex);
o.screenPos = o.vertex.xyw;
o.texcoordStereo = TransformStereoScreenSpaceTex(o.texcoord, 1.0);
return o;
}
このようにワールドスペースの使用は簡単です!
Shader "Hidden/Filter/Test" {
HLSLINCLUDE
#include "../StdLib.hlsl"
float4 Frag(v2f i) : SV_Target {
float2 screenUV = (i.screenPos.xy / i.screenPos.z) * 0.5f + 0.5f;
float depth = SAMPLE_DEPTH_TEXTURE(_CameraDepthTexture,screenUV);
depth = LinearEyeDepth(depth);
float3 worldspace = i.worldDirection * depth + _WorldSpaceCameraPos;
float4 color = float4(worldspace, 1.0);
return color;
}
ENDHLSL
SubShader {
Cull Off ZWrite Off ZTest Always
Pass {
HLSLPROGRAM
#pragma vertex VertDefault
#pragma fragment Frag
ENDHLSL
}
}
}
私はこれに関して多くの問題を抱えていて、これがすべての人にとっての修正であるかどうかはわかりません(2017.3.1p1でMac w/Metalをテスト)が、上記と同じ問題がありました-カメラを移動または回転すると、ワールドスペースの位置が非常に奇妙に変化します。
ここで詳しく説明している古い方法(後処理スタックと統合されていない)でテストしましたが、これは機能します。 - https://github.com/zezba9000/UnityMathReference/tree/master/Assets/Shaders/DepthBuffToWorldPos
後処理スタックで同じものを再作成すると、異なる結果が得られました。少し調べてみると、異なるデータはi.worldDirection
だけでした。これはデフォルトでv.vertex.xy
に基づいています。これをi.texcoord.xy*2-1
に変更しましたが、完全に機能します。
ここにコードがあります(cs +シェーダー):
DrawWorldSpacePosition.cs
using System;
using UnityEngine;
using UnityEngine.Rendering.PostProcessing;
[Serializable]
[PostProcess(typeof(DrawWorldSpacePositionRenderer), PostProcessEvent.AfterStack, "Custom/DrawWorldSpacePosition")]
public sealed class DrawWorldSpacePosition : PostProcessEffectSettings
{
}
public sealed class DrawWorldSpacePositionRenderer : PostProcessEffectRenderer<DrawWorldSpacePosition>
{
public override void Render(PostProcessRenderContext context)
{
var sheet = context.propertySheets.Get(Shader.Find("Hidden/Custom/DrawWorldSpacePosition"));
var camera = context.camera;
var p = GL.GetGPUProjectionMatrix(camera.projectionMatrix, false);// Unity flips its 'Y' vector depending on if its in VR, Editor view or game view etc... (facepalm)
p[2, 3] = p[3, 2] = 0.0f;
p[3, 3] = 1.0f;
var clipToWorld = Matrix4x4.Inverse(p * camera.worldToCameraMatrix) * Matrix4x4.TRS(new Vector3(0, 0, -p[2, 2]), Quaternion.identity, Vector3.one);
sheet.properties.SetMatrix("clipToWorld", clipToWorld);
context.command.BlitFullscreenTriangle(context.source, context.destination, sheet, 0);
}
}
DrawWorldSpacePosition.shader
Shader "Hidden/Custom/DrawWorldSpacePosition"
{
HLSLINCLUDE
#include "../PostProcessing/Shaders/StdLib.hlsl"
TEXTURE2D_SAMPLER2D(_CameraDepthTexture, sampler_CameraDepthTexture);
uniform float4x4 clipToWorld;
struct VaryingsExtended
{
float4 vertex : SV_POSITION;
float2 texcoord : TEXCOORD0;
float2 texcoordStereo : TEXCOORD1;
float3 worldDirection : TEXCOORD2;
};
VaryingsExtended Vert(AttributesDefault v)
{
VaryingsExtended o;
o.vertex = float4(v.vertex.xy, 0.0, 1.0);
o.texcoord = TransformTriangleVertexToUV(v.vertex.xy);
#if UNITY_UV_STARTS_AT_TOP
o.texcoord = o.texcoord * float2(1.0, -1.0) + float2(0.0, 1.0);
#endif
o.texcoordStereo = TransformStereoScreenSpaceTex(o.texcoord, 1.0);
float4 clip = float4(o.texcoord.xy*2-1, 0.0, 1.0);
o.worldDirection = mul(clipToWorld, clip) - _WorldSpaceCameraPos;
return o;
}
float4 Frag(VaryingsExtended i) : SV_Target
{
float depth = SAMPLE_DEPTH_TEXTURE(_CameraDepthTexture, sampler_CameraDepthTexture, i.texcoordStereo);
depth = LinearEyeDepth(depth);
float3 worldspace = i.worldDirection * depth + _WorldSpaceCameraPos;
float4 color = float4(worldspace, 1.0);
return color;
}
ENDHLSL
SubShader
{
Cull Off ZWrite Off ZTest Always
Pass
{
HLSLPROGRAM
#pragma vertex Vert
#pragma fragment Frag
ENDHLSL
}
}
}