gpt4 book ai didi

c++ - HLSL 中的镜面反射

转载 作者:太空狗 更新时间:2023-10-29 20:12:37 27 4
gpt4 key购买 nike

我正在尝试了解 HLSL 和 DirectX11 中的镜面反射

cbuffer ConstantBuffer : register( b0 )
{
matrix World; // Матрица мира
matrix View; // Матрица вида
matrix Projection; // Матрица проекции
float4 vLightDir[3]; // Dir of light
float4 vLightColor[3]; // color of light
float4 vOutputColor; // Active color
//float3 Eye;
}

struct VS_INPUT // Входящие данные вершинного шейдера
{
float4 Pos : POSITION; // Позиция по X, Y, Z
float3 Norm : NORMAL; // Нормаль по X, Y, Z
};

struct PS_INPUT // Входящие данные пиксельного шейдера
{
float4 Pos : SV_POSITION; // Позиция пикселя в проекции (экранная)
float3 Norm : TEXCOORD0; // Относительная нормаль пикселя по tu, tv
};


PS_INPUT VS( VS_INPUT input )
{
PS_INPUT output = (PS_INPUT)0;
output.Pos = mul( input.Pos, World );
output.Pos = mul( output.Pos, View );
output.Pos = mul( output.Pos, Projection );
output.Norm = mul( input.Norm, World );

return output;
}


float4 Diffuse( PS_INPUT input) : SV_Target
{
float4 diffuse = float4(1.0, 1.0, 1.0, 1.0);
float4 finalColor = diffuse *0.1;

// Adding all light colours
for(int i=0; i<3; i++)
{
finalColor += saturate( dot( (float3)vLightDir[i], input.Norm) * vLightColor[i] );
}
finalColor.a = 1;
return finalColor;
}

float4 Specular(PS_INPUT input) : SV_Target
{
float4 diffuse = float4(1.0, 0.0, 0.0, 1.0);
float4 finalColor = diffuse *0.1;
float3 Eye = float3(0.0f, 4.0f, -20.0f);
float4 intensity = 0.1;
float power = 4;

float3 R = reflect(-normalize(Eye), input.Norm);
for (int i = 0; i < 3; i++)
{
finalColor += saturate(intensity * vLightColor[i] * pow(dot(R, Eye), power));
}
return finalColor;
}


float4 PSSolid( PS_INPUT input) : SV_Target
{
return vOutputColor;
}

现在我只有漫反射,镜面反射只显示白色立方体。 :(我在哪里可以获得有关镜面反射的示例或教程?

最佳答案

您要实现的目标称为 Phong Reflection Model它通过计算法线 vector 和光线方向 vector 之间的反射 vector 来生成镜面高光。然后使用点积计算反射 vector 与从表面到眼睛位置的 vector 之间的角度的余弦。

Specular 着色器存在一些问题。

首先,您的Eye vector 不正确。它需要是从表面到眼睛位置的 vector 。目前,您只使用一个职位。为此,您需要修改顶点着色器以输出顶点位置世界空间 位置。为此添加:

float3 WorldPos : TEXCOORD1;

到您的PS_INPUT。现在计算顶点着色器中的世界空间顶点位置:

output.WorldPos = mul( input.Pos, World );

这个值将被发送到像素着色器并在像素之间进行插值,以便它给出像素的世界位置。使用它,您可以在像素着色器中计算从像素到眼睛位置的 View vector V。为此,请使用:

float3 V = normalize( Eye - input.WorldPos );

现在,反射 vector R 是通过围绕表面法线(而不是眼睛位置)反射入射光方向创建的,并且必须为循环中的每个光计算它:

float3 R = reflect( normalize( vLightDir[i] ), normalize( input.Norm ) );

请注意,在这个等式中,光 vector 是从光指向表面(所以​​不要像下面描述的那样取反)。

现在您已准备好使用 RV 之间的点积来计算每盏灯产生的镜面反射分量:

finalColor += intensity * vLightColor[i] * pow( saturate( dot( R, V ) ), power );

我看到的最后一个问题是您没有在 Specular 着色器中正确计算漫反射。如果您希望不面向光线的区域更暗,则需要像您的 Diffuse 着色器一样执行此操作。但是,不是直接使用 vLightDir[i],而是需要取反,使其从表面指向光:

float3 L = -normalize( vLightDir[i].xyz );

一种比 Phong 反射模型 更便宜的方法称为 Blinn-Phong Reflection Model .它不使用 R,而是使用这个简单的等式计算 VL 之间的半 vector :

float3 H = normalize( L + V );

现在计算镜面反射时不再使用dot( R, V ),而是使用:

dot( N, H );

关于c++ - HLSL 中的镜面反射,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/26639402/

27 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com