Re: mv1から直に法線マップを指定した際のシェーダーの挙動 ( No.1 ) |
- 名前:名無三 日時:2024/06/06 00:40
最低限のサンプルコードになります。右手前がノーマルマップ付きモデルに自前シェーダーを入れたものとなり、当環境では表示できなくなります。
(追記:もしよろしければコードブロックか折りたたみ機能を掲示板に追加下さると嬉しいです、すいません)
#include "DxLib.h"
#include <array>
#include <functional>
class ShaderUseClass {
public:
//2Dにシェーダーを適用する際に使用する画面サイズの頂点情報
class ScreenVertex {
VERTEX3DSHADER Screen_vertex[6] = {};
public:
// 頂点データの取得
const auto* GetScreenVertex() noexcept { return Screen_vertex; }
// 頂点データの準備
void SetScreenVertex(int dispx, int dispy) noexcept {
int xp1 = 0;
int yp1 = dispy;
int xp2 = dispx;
int yp2 = 0;
Screen_vertex[0].pos = VGet((float)xp1, (float)yp1, 0.0f);
Screen_vertex[1].pos = VGet((float)xp2, (float)yp1, 0.0f);
Screen_vertex[2].pos = VGet((float)xp1, (float)yp2, 0.0f);
Screen_vertex[3].pos = VGet((float)xp2, (float)yp2, 0.0f);
Screen_vertex[0].dif = GetColorU8(255, 255, 255, 255);
Screen_vertex[1].dif = GetColorU8(255, 255, 255, 255);
Screen_vertex[2].dif = GetColorU8(255, 255, 255, 255);
Screen_vertex[3].dif = GetColorU8(255, 255, 255, 255);
Screen_vertex[0].u = 0.0f; Screen_vertex[0].v = 0.0f;
Screen_vertex[1].u = 1.0f; Screen_vertex[1].v = 0.0f;
Screen_vertex[2].u = 0.0f; Screen_vertex[3].v = 1.0f;
Screen_vertex[3].u = 1.0f; Screen_vertex[2].v = 1.0f;
Screen_vertex[4] = Screen_vertex[2];
Screen_vertex[5] = Screen_vertex[1];
}
};
// 影用の深度記録画像を作成した際のカメラのビュー行列と射影行列
struct LIGHTCAMERA_MATRIX {
MATRIX ViewMatrix;
MATRIX ProjectionMatrix;
};
private:
//シェーダーハンドル
int m_VertexShaderhandle{-1};
int m_PixelShaderhandle{-1};
//シェーダーに渡す追加パラメーターを配するハンドル
std::array<int, 4> LightCameraMatrixConstantBufferHandle{-1}; // 影用の深度記録画像を作成した際のカメラのビュー行列と射影行列を設定するための定数バッファ
std::array<int, 4> m_VertexShadercbhandle{-1};
int m_PixelShaderSendDispSizeHandle{-1};
std::array<int, 4> m_PixelShadercbhandle{-1};
public:
ShaderUseClass() {
//シェーダーハンドル
m_VertexShaderhandle = -1;
m_PixelShaderhandle = -1;
//シェーダーに渡す追加パラメーターを配するハンドル
for (auto& h : m_VertexShadercbhandle) { h = -1; }
m_PixelShaderSendDispSizeHandle = -1;
for (auto& h : m_PixelShadercbhandle) { h = -1; }
}
~ShaderUseClass() {
Dispose();
}
public:
//初期化
void Init(const char* VertexShader, const char* PixelShader) noexcept {
if (GetUseDirect3DVersion() != DX_DIRECT3D_11) { return; }
//頂点シェーダー周り
for (auto& h : m_VertexShadercbhandle) {
h = CreateShaderConstantBuffer(sizeof(float) * 4);
}
// 影用の深度記録画像を作成した際のカメラのビュー行列と射影行列を設定するための定数バッファの作成
for (auto& h : LightCameraMatrixConstantBufferHandle) {
h = CreateShaderConstantBuffer(sizeof(LIGHTCAMERA_MATRIX));
}
this->m_VertexShaderhandle = LoadVertexShader(VertexShader); // 頂点シェーダーバイナリコードの読み込み
//ピクセルシェーダ―周り
this->m_PixelShaderSendDispSizeHandle = CreateShaderConstantBuffer(sizeof(float) * 4);
for (auto& h : m_PixelShadercbhandle) {
h = CreateShaderConstantBuffer(sizeof(float) * 4);
}
this->m_PixelShaderhandle = LoadPixelShader(PixelShader); // ピクセルシェーダーバイナリコードの読み込み
}
//後始末
void Dispose() noexcept {
if (GetUseDirect3DVersion() != DX_DIRECT3D_11) { return; }
//頂点シェーダー周り
for (auto& h : LightCameraMatrixConstantBufferHandle) {
DeleteShaderConstantBuffer(h);
}
for (auto& h : m_VertexShadercbhandle) {
DeleteShaderConstantBuffer(h);
}
DeleteShader(this->m_VertexShaderhandle);
//ピクセルシェーダ―周り
DeleteShaderConstantBuffer(this->m_PixelShaderSendDispSizeHandle);
for (auto& h : m_PixelShadercbhandle) {
DeleteShaderConstantBuffer(h);
}
DeleteShader(this->m_PixelShaderhandle);
}
public:
//頂点シェーダ―のSlot番目のレジスタに情報をセット(Slot>=4)
void SetVertexParam(int Slot, float param1, float param2, float param3, float param4) noexcept {
if (GetUseDirect3DVersion() != DX_DIRECT3D_11) { return; }
FLOAT4* f4 = (FLOAT4 *)GetBufferShaderConstantBuffer(this->m_VertexShadercbhandle[0]); // 頂点シェーダー用の定数バッファのアドレスを取得
f4->x = param1;
f4->y = param2;
f4->z = param3;
f4->w = param4;
UpdateShaderConstantBuffer(this->m_VertexShadercbhandle[0]); // 頂点シェーダー用の定数バッファを更新して書き込んだ内容を反映する
SetShaderConstantBuffer(this->m_VertexShadercbhandle[0], DX_SHADERTYPE_VERTEX, Slot); // 頂点シェーダーの定数バッファを定数バッファレジスタ4にセット
}
//ピクセルシェーダ―の2番目のレジスタに画面サイズの情報をセット
void SetPixelDispSize(int dispx, int dispy) noexcept {
if (GetUseDirect3DVersion() != DX_DIRECT3D_11) { return; }
FLOAT2* dispsize = (FLOAT2*)GetBufferShaderConstantBuffer(this->m_PixelShaderSendDispSizeHandle); // ピクセルシェーダー用の定数バッファのアドレスを取得
dispsize->u = (float)dispx;
dispsize->v = (float)dispy;
UpdateShaderConstantBuffer(this->m_PixelShaderSendDispSizeHandle); // ピクセルシェーダー用の定数バッファを更新して書き込んだ内容を反映する
SetShaderConstantBuffer(this->m_PixelShaderSendDispSizeHandle, DX_SHADERTYPE_PIXEL, 2); // ピクセルシェーダー用の定数バッファを定数バッファレジスタ2にセット
}
//ピクセルシェーダ―のSlot番目のレジスタに情報をセット(Slot>=3)
void SetPixelParam(int Slot, float param1, float param2, float param3, float param4) noexcept {
if (GetUseDirect3DVersion() != DX_DIRECT3D_11) { return; }
FLOAT4* f4 = (FLOAT4*)GetBufferShaderConstantBuffer(this->m_PixelShadercbhandle.at(Slot - 3)); // ピクセルシェーダー用の定数バッファのアドレスを取得
f4->x = param1;
f4->y = param2;
f4->z = param3;
f4->w = param4;
UpdateShaderConstantBuffer(this->m_PixelShadercbhandle.at(Slot - 3)); // ピクセルシェーダー用の定数バッファを更新して書き込んだ内容を反映する
SetShaderConstantBuffer(this->m_PixelShadercbhandle.at(Slot - 3), DX_SHADERTYPE_PIXEL, Slot); // ピクセルシェーダー用の定数バッファを定数バッファレジスタ3にセット
}
//3D空間に適用する場合の関数(引数に3D描画のラムダ式を代入)
void Draw_lamda(std::function<void()> doing) noexcept {
if (GetUseDirect3DVersion() != DX_DIRECT3D_11) {
doing();
return;
}
SetUseVertexShader(this->m_VertexShaderhandle); // 使用する頂点シェーダーをセット
SetUsePixelShader(this->m_PixelShaderhandle); // 使用するピクセルシェーダーをセット
MV1SetUseOrigShader(TRUE);
doing();
MV1SetUseOrigShader(FALSE);
SetUseVertexShader(-1);
SetUsePixelShader(-1);
}
//2D画像に適用する場合の関数
void Draw(ScreenVertex& Screenvertex) noexcept {
if (GetUseDirect3DVersion() != DX_DIRECT3D_11) { return; }
Draw_lamda([&] {DrawPolygon3DToShader(Screenvertex.GetScreenVertex(), 2); });
}
};
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow) {
ChangeWindowMode(TRUE);
// DXライブラリの初期化
if (DxLib_Init() < 0) return -1;
ShaderUseClass m_PBR_Shader;
int model1 = MV1LoadModel("Chara/model_DISABLE.mv1");
int model2 = MV1LoadModel("Chara/model_Normal.mv1");
m_PBR_Shader.Init("Shader/VS_PBR3D.vso", "Shader/PS_PBR3D.pso");
// メインループ
while (ProcessMessage() == 0) {
SetDrawScreen(DX_SCREEN_BACK);
ClearDrawScreen();
SetCameraNearFar(0.1f*12.5f, 10.f*12.5f);
SetCameraPositionAndTarget_UpVecY(VGet(0, 1.5f*12.5f, -3.f*12.5f), VGet(0.f, 1.5f*12.5f, 0.f));
{
MV1SetPosition(model1, VGet(-1.5f*12.5f, 0.f, 0.f));
MV1SetPosition(model2, VGet(1.5f*12.5f, 0.f, 0.f));
m_PBR_Shader.Draw_lamda([&]() {
MV1DrawModel(model1);
MV1DrawModel(model2);
});
MV1SetPosition(model1, VGet(-1.5f*12.5f, 0.f, 10.f));
MV1SetPosition(model2, VGet(1.5f*12.5f, 0.f, 10.f));
MV1DrawModel(model1);
MV1DrawModel(model2);
}
ScreenFlip();
}
m_PBR_Shader.Dispose();
DxLib_End();
return 0;
}
|
Re: mv1から直に法線マップを指定した際のシェーダーの挙動 ( No.2 ) |
- 名前:管理人 日時:2024/06/07 21:45
> 処理内では法線マップのあるなしで挙動が変わるようになっておりますでしょうか?
はい、法線マップがある場合は頂点データに『接線( Tangent )』と『従法線( Binormal )』が加わります
// 法線マップが無い場合
struct VS_INPUT
{
float3 Position : POSITION ; // 座標( ローカル空間 )
float3 Normal : NORMAL ; // 法線( ローカル空間 )
float4 Diffuse : COLOR0 ; // ディフューズカラー
float4 Specular : COLOR1 ; // スペキュラカラー
float4 TexCoords0 : TEXCOORD0 ; // テクスチャ座標
float4 TexCoords1 : TEXCOORD1 ; // サブテクスチャ座標
int4 BlendIndices0 : BLENDINDICES0 ; // ボーン処理用 Float型定数配列インデックス0
float4 BlendWeight0 : BLENDWEIGHT0 ; // ボーン処理用ウエイト値0
} ;
// 法線マップが有る場合
struct VS_INPUT
{
float3 Position : POSITION ; // 座標( ローカル空間 )
float3 Normal : NORMAL ; // 法線( ローカル空間 )
float4 Diffuse : COLOR0 ; // ディフューズカラー
float4 Specular : COLOR1 ; // スペキュラカラー
float4 TexCoords0 : TEXCOORD0 ; // テクスチャ座標
float4 TexCoords1 : TEXCOORD1 ; // サブテクスチャ座標
float3 Tan : TANGENT0 ; // 接線( ローカル空間 )
float3 Bin : BINORMAL0 ; // 従法線( ローカル空間 )
int4 BlendIndices0 : BLENDINDICES0 ; // ボーン処理用 Float型定数配列インデックス0
float4 BlendWeight0 : BLENDWEIGHT0 ; // ボーン処理用ウエイト値0
} ;
法線を頂点の法線データからそのまま使う場合と異なり法線マップから法線を取得する形になるので
法線周りの処理も大きく変化します
掲示板のご返信で説明するのは難しいので、DXライブラリのソースパッケージの中の
Shader-> Windows -> Direct3D11 -> MV1DefaultShader フォルダの中にある
MV1Default_VertexLighting_VS.hlsl と MV1Default_VertexLighting_PS.hlsl の中の
#if BUMPMAP と書かれている辺りに記述されている法線関係の処理をご覧になってみてください m(_ _;m
> (追記:もしよろしければコードブロックか折りたたみ機能を掲示板に追加下さると嬉しいです、すいません)
すみません、現状の掲示板のプログラムは掲示板素材サイトから貰ってきたものなので、
自前でコードブロック機能を追加するのはちょっと無理です m(_ _;m
|
Re: mv1から直に法線マップを指定した際のシェーダーの挙動 ( No.3 ) |
- 名前:名無三(解決) 日時:2024/06/08 06:20
すいません、追加でデータが必要な点承知しました!
後から添付するコードで正常に表示を行うことができました、ありがとうございます!
コードブロックの件承知しました!
すいません、MV1Default_VertexLighting_PSを参考にさせていただいた際に気になったのですが、
以下の箇所はそれぞれでNormalに持たせるデータが異なるという認識でよろしいでしょうか?
BUMPMAPの際→Normalはテクスチャ上の法線でライトのベクトルを接地空間に変換して比較
そうでない場合→Normalはビュー法線でライトのベクトルとそのまま比較
// 法線の準備
#if BUMPMAP
// 法線の 0〜1 の値を -1.0〜1.0 に変換する
Normal = ( g_NormalMapTexture.Sample( g_NormalMapSampler, PSInput.TexCoords0_1.xy ).rgb - 0.5f ) * 2.0f ;
#else // BUMPMAP
Normal = normalize( PSInput.VNormal ) ;
#endif // BUMPMAP
〜中略〜
// ディフューズ角度減衰率計算
#ifdef BUMPMAP
lLightTemp.x = dot( VTan, -lLightDir ) ;
lLightTemp.y = dot( VBin, -lLightDir ) ;
lLightTemp.z = dot( VNrm, -lLightDir ) ;
DiffuseAngleGen = saturate( dot( Normal, normalize( lLightTemp.xyz ) ) ) ;
#else // BUMPMAP
DiffuseAngleGen = saturate( dot( Normal, -lLightDir ) ) ;
#endif // BUMPMAP
|
Re: mv1から直に法線マップを指定した際のシェーダーの挙動 ( No.4 ) |
- 名前:名無三 日時:2024/06/08 06:22
ーーー頂点シェーダーーーー
// 頂点シェーダーの入力
struct VS_INPUT
{
float4 Position : POSITION; // 座標( ローカル空間 )
float3 Normal : NORMAL0; // 法線( ローカル空間 )
float4 Diffuse : COLOR0; // ディフューズカラー
float4 Specular : COLOR1; // スペキュラカラー
float4 TexCoords0 : TEXCOORD0; // テクスチャ座標
float4 TexCoords1 : TEXCOORD1; // サブテクスチャ座標
float3 Tan : TANGENT0; // 接線( ローカル空間 )
float3 Bin : BINORMAL0; // 従法線( ローカル空間 )
int4 BlendIndices0 : BLENDINDICES0; // スキニング処理用 Float型定数配列インデックス
float4 BlendWeight0 : BLENDWEIGHT0; // スキニング処理用ウエイト値
} ;
// 頂点シェーダーの出力
struct VS_OUTPUT
{
float2 TexCoords0 : TEXCOORD0; // テクスチャ座標
float3 VPosition : TEXCOORD1; // 座標( ビュー空間 )
float4x4 VMat : TEXCOORD2; // 接線( ビュー空間 )
float4 Specular : COLOR1; // スペキュラカラー
float4 Position : SV_POSITION; // 座標( プロジェクション空間 )
} ;
// マテリアルパラメータ
struct DX_D3D11_CONST_MATERIAL {
float4 Diffuse; // ディフューズカラー
float4 Specular; // スペキュラカラー
float4 Ambient_Emissive; // マテリアルエミッシブカラー + マテリアルアンビエントカラー * グローバルアンビエントカラー
float Power; // スペキュラの強さ
float TypeParam0; // マテリアルタイプパラメータ0
float TypeParam1; // マテリアルタイプパラメータ1
float TypeParam2; // マテリアルタイプパラメータ2
};
// フォグパラメータ
struct DX_D3D11_VS_CONST_FOG {
float LinearAdd; // フォグ用パラメータ end / ( end - start )
float LinearDiv; // フォグ用パラメータ -1 / ( end - start )
float Density; // フォグ用パラメータ density
float E; // フォグ用パラメータ 自然対数の低
float4 Color; // カラー
};
// ライトパラメータ
struct DX_D3D11_CONST_LIGHT {
int Type; // ライトタイプ( DX_LIGHTTYPE_POINT など )
int3 Padding1; // パディング1
float3 Position; // 座標( ビュー空間 )
float RangePow2; // 有効距離の2乗
float3 Direction; // 方向( ビュー空間 )
float FallOff; // スポットライト用FallOff
float3 Diffuse; // ディフューズカラー
float SpotParam0; // スポットライト用パラメータ0( cos( Phi / 2.0f ) )
float3 Specular; // スペキュラカラー
float SpotParam1; // スポットライト用パラメータ1( 1.0f / ( cos( Theta / 2.0f ) - cos( Phi / 2.0f ) ) )
float4 Ambient; // アンビエントカラーとマテリアルのアンビエントカラーを乗算したもの
float Attenuation0; // 距離による減衰処理用パラメータ0
float Attenuation1; // 距離による減衰処理用パラメータ1
float Attenuation2; // 距離による減衰処理用パラメータ2
float Padding2; // パディング2
};
// ピクセルシェーダー・頂点シェーダー共通パラメータ
struct DX_D3D11_CONST_BUFFER_COMMON {
DX_D3D11_CONST_LIGHT Light[6]; // ライトパラメータ
DX_D3D11_CONST_MATERIAL Material; // マテリアルパラメータ
DX_D3D11_VS_CONST_FOG Fog; // フォグパラメータ
};
// 基本パラメータ
struct DX_D3D11_VS_CONST_BUFFER_BASE
{
float4 AntiViewportMatrix[ 4 ] ; // アンチビューポート行列
float4 ProjectionMatrix[ 4 ] ; // ビュー → プロジェクション行列
float4 ViewMatrix[ 3 ] ; // ワールド → ビュー行列
float4 LocalWorldMatrix[ 3 ] ; // ローカル → ワールド行列
float4 ToonOutLineSize ; // トゥーンの輪郭線の大きさ
float DiffuseSource ; // ディフューズカラー( 0.0f:マテリアル 1.0f:頂点 )
float SpecularSource ; // スペキュラカラー( 0.0f:マテリアル 1.0f:頂点 )
float MulSpecularColor ; // スペキュラカラー値に乗算する値( スペキュラ無効処理で使用 )
float Padding ;
} ;
// その他の行列
struct DX_D3D11_VS_CONST_BUFFER_OTHERMATRIX
{
float4 ShadowMapLightViewProjectionMatrix[ 3 ][ 4 ] ; // シャドウマップ用のライトビュー行列とライト射影行列を乗算したもの
float4 TextureMatrix[ 3 ][ 2 ] ; // テクスチャ座標操作用行列
} ;
// スキニングメッシュ用の ローカル → ワールド行列
struct DX_D3D11_VS_CONST_BUFFER_LOCALWORLDMATRIX {
float4 Matrix[54 * 3]; // ローカル → ワールド行列
};
// 頂点シェーダー・ピクセルシェーダー共通パラメータ
cbuffer cbD3D11_CONST_BUFFER_COMMON : register(b0) {
DX_D3D11_CONST_BUFFER_COMMON g_Common;
};
// 基本パラメータ
cbuffer cbD3D11_CONST_BUFFER_VS_BASE : register( b1 )
{
DX_D3D11_VS_CONST_BUFFER_BASE g_Base ;
} ;
// その他の行列
cbuffer cbD3D11_CONST_BUFFER_VS_OTHERMATRIX : register( b2 )
{
DX_D3D11_VS_CONST_BUFFER_OTHERMATRIX g_OtherMatrix ;
} ;
// スキニングメッシュ用の ローカル → ワールド行列
cbuffer cbD3D11_CONST_BUFFER_VS_LOCALWORLDMATRIX : register(b3) {
DX_D3D11_VS_CONST_BUFFER_LOCALWORLDMATRIX g_LocalWorldMatrix;
};
// main関数
VS_OUTPUT main( VS_INPUT VSInput )
{
VS_OUTPUT VSOutput ;
float4 lWorldPosition ;
float4 lViewPosition ;
float3 lWorldNrm ;
float3 lViewNrm ;
float4 lLocalWorldMatrix[3];
float3 lWorldTan;
float3 lWorldBin;
float3 lViewTan;
float3 lViewBin;
// 複数のフレームのブレンド行列の作成
lLocalWorldMatrix[0] = g_LocalWorldMatrix.Matrix[VSInput.BlendIndices0.x + 0] * VSInput.BlendWeight0.x;
lLocalWorldMatrix[1] = g_LocalWorldMatrix.Matrix[VSInput.BlendIndices0.x + 1] * VSInput.BlendWeight0.x;
lLocalWorldMatrix[2] = g_LocalWorldMatrix.Matrix[VSInput.BlendIndices0.x + 2] * VSInput.BlendWeight0.x;
lLocalWorldMatrix[0] += g_LocalWorldMatrix.Matrix[VSInput.BlendIndices0.y + 0] * VSInput.BlendWeight0.y;
lLocalWorldMatrix[1] += g_LocalWorldMatrix.Matrix[VSInput.BlendIndices0.y + 1] * VSInput.BlendWeight0.y;
lLocalWorldMatrix[2] += g_LocalWorldMatrix.Matrix[VSInput.BlendIndices0.y + 2] * VSInput.BlendWeight0.y;
lLocalWorldMatrix[0] += g_LocalWorldMatrix.Matrix[VSInput.BlendIndices0.z + 0] * VSInput.BlendWeight0.z;
lLocalWorldMatrix[1] += g_LocalWorldMatrix.Matrix[VSInput.BlendIndices0.z + 1] * VSInput.BlendWeight0.z;
lLocalWorldMatrix[2] += g_LocalWorldMatrix.Matrix[VSInput.BlendIndices0.z + 2] * VSInput.BlendWeight0.z;
lLocalWorldMatrix[0] += g_LocalWorldMatrix.Matrix[VSInput.BlendIndices0.w + 0] * VSInput.BlendWeight0.w;
lLocalWorldMatrix[1] += g_LocalWorldMatrix.Matrix[VSInput.BlendIndices0.w + 1] * VSInput.BlendWeight0.w;
lLocalWorldMatrix[2] += g_LocalWorldMatrix.Matrix[VSInput.BlendIndices0.w + 2] * VSInput.BlendWeight0.w;
// 頂点座標変換 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++( 開始 )
// ローカル座標をワールド座標に変換
lWorldPosition.x = dot(VSInput.Position, lLocalWorldMatrix[0]);
lWorldPosition.y = dot(VSInput.Position, lLocalWorldMatrix[1]);
lWorldPosition.z = dot(VSInput.Position, lLocalWorldMatrix[2]);
lWorldPosition.w = 1.0f ;
// ワールド座標をビュー座標に変換
lViewPosition.x = dot(lWorldPosition, g_Base.ViewMatrix[0]);
lViewPosition.y = dot(lWorldPosition, g_Base.ViewMatrix[1]);
lViewPosition.z = dot(lWorldPosition, g_Base.ViewMatrix[2]);
lViewPosition.w = 1.0f;
// ビュー座標を射影座標に変換
VSOutput.Position.x = dot(lViewPosition, g_Base.ProjectionMatrix[0]);
VSOutput.Position.y = dot(lViewPosition, g_Base.ProjectionMatrix[1]);
VSOutput.Position.z = dot(lViewPosition, g_Base.ProjectionMatrix[2]);
VSOutput.Position.w = dot(lViewPosition, g_Base.ProjectionMatrix[3]);
// 頂点座標変換 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++( 終了 )
// 法線をビュー空間の角度に変換 =========================================( 開始 )
// ローカルベクトルをワールドベクトルに変換
lWorldNrm.x = dot(VSInput.Normal, lLocalWorldMatrix[0].xyz);
lWorldNrm.y = dot(VSInput.Normal, lLocalWorldMatrix[1].xyz);
lWorldNrm.z = dot(VSInput.Normal, lLocalWorldMatrix[2].xyz);
// ワールドベクトルをビューベクトルに変換
lViewNrm.x = dot(lWorldNrm, g_Base.ViewMatrix[0].xyz);
lViewNrm.y = dot(lWorldNrm, g_Base.ViewMatrix[1].xyz);
lViewNrm.z = dot(lWorldNrm, g_Base.ViewMatrix[2].xyz);
// 法線をビュー空間の角度に変換 =========================================( 終了 )
// 出力パラメータセット ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++( 開始 )
// 頂点座標を保存
VSOutput.VPosition = lViewPosition.xyz ;
// 従法線、接線、法線をもとに接空間行列を作成
lWorldTan.x = dot(VSInput.Tan, lLocalWorldMatrix[0].xyz);
lWorldTan.y = dot(VSInput.Tan, lLocalWorldMatrix[1].xyz);
lWorldTan.z = dot(VSInput.Tan, lLocalWorldMatrix[2].xyz);
lWorldBin.x = dot(VSInput.Bin, lLocalWorldMatrix[0].xyz);
lWorldBin.y = dot(VSInput.Bin, lLocalWorldMatrix[1].xyz);
lWorldBin.z = dot(VSInput.Bin, lLocalWorldMatrix[2].xyz);
lViewTan.x = dot(lWorldTan, g_Base.ViewMatrix[0].xyz);
lViewTan.y = dot(lWorldTan, g_Base.ViewMatrix[1].xyz);
lViewTan.z = dot(lWorldTan, g_Base.ViewMatrix[2].xyz);
lViewBin.x = dot(lWorldBin, g_Base.ViewMatrix[0].xyz);
lViewBin.y = dot(lWorldBin, g_Base.ViewMatrix[1].xyz);
lViewBin.z = dot(lWorldBin, g_Base.ViewMatrix[2].xyz);
float4x4 mat = {
float4(normalize(lViewTan), 0.0f),
float4(normalize(lViewBin), 0.0f),
float4(normalize(lViewNrm), 0.0f),
{0,0,0,1}
};
VSOutput.VMat = mat;
// テクスチャ座標変換行列による変換を行った結果のテクスチャ座標をセット
VSOutput.TexCoords0.x = dot( VSInput.TexCoords0, g_OtherMatrix.TextureMatrix[ 0 ][ 0 ] ) ;
VSOutput.TexCoords0.y = dot( VSInput.TexCoords0, g_OtherMatrix.TextureMatrix[ 0 ][ 1 ] ) ;
// 出力パラメータセット ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++( 終了 )
// スペキュラカラーをセット
VSOutput.Specular = (g_Base.SpecularSource > 0.5f ? VSInput.Specular : g_Common.Material.Specular) * g_Base.MulSpecularColor;
// 出力パラメータを返す
return VSOutput ;
}
|
Re: mv1から直に法線マップを指定した際のシェーダーの挙動 ( No.5 ) |
- 名前:名無三 日時:2024/06/08 06:23
ーーーピクセルシェーダーーーー
// defines
#define PI 3.14159265359
#define EPSILON 1e-6
#define DX_LIGHTTYPE_POINT (1) // D_D3DLIGHT_POINT
#define DX_LIGHTTYPE_SPOT (2) // D_D3DLIGHT_SPOT
#define DX_LIGHTTYPE_DIRECTIONAL (3) // D_D3DLIGHT_DIRECTIONAL
// ピクセルシェーダーの入力
struct PS_INPUT
{
float2 TexCoords0 : TEXCOORD0 ; // テクスチャ座標
float3 VPosition : TEXCOORD1 ; // 座標( ビュー空間 )
float4x4 VMat : TEXCOORD2; // 接線( ビュー空間 )
float4 Specular : COLOR1; // スペキュラカラー
} ;
// ピクセルシェーダーの出力
struct PS_OUTPUT
{
float4 Color0 : SV_TARGET0 ; // 色
float4 Normal : SV_TARGET1; // 法線( ビュー空間 )
float4 Depth : SV_TARGET2; // 深度
} ;
// マテリアルパラメータ
struct DX_D3D11_CONST_MATERIAL
{
float4 Diffuse ; // ディフューズカラー
float4 Specular ; // スペキュラカラー
float4 Ambient_Emissive ; // マテリアルエミッシブカラー + マテリアルアンビエントカラー * グローバルアンビエントカラー
float Power ; // スペキュラの強さ
float TypeParam0 ; // マテリアルタイプパラメータ0
float TypeParam1 ; // マテリアルタイプパラメータ1
float TypeParam2 ; // マテリアルタイプパラメータ2
} ;
// フォグパラメータ
struct DX_D3D11_VS_CONST_FOG
{
float LinearAdd ; // フォグ用パラメータ end / ( end - start )
float LinearDiv ; // フォグ用パラメータ -1 / ( end - start )
float Density ; // フォグ用パラメータ density
float E ; // フォグ用パラメータ 自然対数の低
float4 Color ; // カラー
} ;
// ライトパラメータ
struct DX_D3D11_CONST_LIGHT
{
int Type ; // ライトタイプ( DX_LIGHTTYPE_POINT など )
int3 Padding1 ; // パディング1
float3 Position ; // 座標( ビュー空間 )
float RangePow2 ; // 有効距離の2乗
float3 Direction ; // 方向( ビュー空間 )
float FallOff ; // スポットライト用FallOff
float3 Diffuse ; // ディフューズカラー
float SpotParam0 ; // スポットライト用パラメータ0( cos( Phi / 2.0f ) )
float3 Specular ; // スペキュラカラー
float SpotParam1 ; // スポットライト用パラメータ1( 1.0f / ( cos( Theta / 2.0f ) - cos( Phi / 2.0f ) ) )
float4 Ambient ; // アンビエントカラーとマテリアルのアンビエントカラーを乗算したもの
float Attenuation0 ; // 距離による減衰処理用パラメータ0
float Attenuation1 ; // 距離による減衰処理用パラメータ1
float Attenuation2 ; // 距離による減衰処理用パラメータ2
float Padding2 ; // パディング2
} ;
// ピクセルシェーダー・頂点シェーダー共通パラメータ
struct DX_D3D11_CONST_BUFFER_COMMON
{
DX_D3D11_CONST_LIGHT Light[ 6 ] ; // ライトパラメータ
DX_D3D11_CONST_MATERIAL Material ; // マテリアルパラメータ
DX_D3D11_VS_CONST_FOG Fog ; // フォグパラメータ
} ;
// 定数バッファピクセルシェーダー基本パラメータ
struct DX_D3D11_PS_CONST_BUFFER_BASE
{
float4 FactorColor ; // アルファ値等
float MulAlphaColor ; // カラーにアルファ値を乗算するかどうか( 0.0f:乗算しない 1.0f:乗算する )
float AlphaTestRef ; // アルファテストで使用する比較値
float2 Padding1 ;
int AlphaTestCmpMode ; // アルファテスト比較モード( DX_CMP_NEVER など )
int3 Padding2 ;
float4 IgnoreTextureColor ; // テクスチャカラー無視処理用カラー
} ;
// 頂点シェーダー・ピクセルシェーダー共通パラメータ
cbuffer cbD3D11_CONST_BUFFER_COMMON : register( b0 )
{
DX_D3D11_CONST_BUFFER_COMMON g_Common ;
} ;
// 基本パラメータ
cbuffer cbD3D11_CONST_BUFFER_PS_BASE : register( b1 )
{
DX_D3D11_PS_CONST_BUFFER_BASE g_Base ;
} ;
// C++ 側で設定するテクスチャや定数の定義
SamplerState g_DiffuseMapSampler : register( s0 ) ; // ディフューズマップテクスチャ
Texture2D g_DiffuseMapTexture : register( t0 ) ; // ディフューズマップテクスチャ
SamplerState g_NormalMapSampler : register(s1); // 法線マップテクスチャ
Texture2D g_NormalMapTexture : register(t1); // 法線マップテクスチャ
SamplerState g_SpecularMapSampler : register(s2); // スペキュラマップテクスチャ
Texture2D g_SpecularMapTexture : register(t2); // スペキュラマップテクスチャ
struct IncidentLight
{
float3 color;
float3 direction;
bool visible;
};
struct ReflectedLight
{
float3 directDiffuse;
float3 directSpecular;
};
struct GeometricContext
{
float3 position;
float3 normal;
float3 viewDir;
};
struct Material
{
float3 diffuseColor;
float specularRoughness;
float3 specularColor;
};
// lights
float punctualLightIntensityToIrradianceFactorDX(const in float lightDistance, const in float Attenuation0, const in float Attenuation1, const in float Attenuation2)
{
// 減衰率の計算 lLightGen = 1 / ( 減衰値0 + 減衰値1 * 距離 + 減衰値2 * ( 距離 * 距離 ) )
return 1.0f / (Attenuation0 + Attenuation1 * lightDistance + Attenuation2 * (lightDistance * lightDistance));
}
float punctualLightIntensityToIrradianceFactor(const in float lightDistance, const in float cutoffDistance, const in float decayExponent)
{
if (decayExponent > 0.0)
{
return pow(saturate(-lightDistance / cutoffDistance + 1.0), decayExponent);
}
return 1.0;
}
void getDirectionalDirectLightIrradiance(const in DX_D3D11_CONST_LIGHT Light, const in GeometricContext geometry, out IncidentLight directLight)
{
directLight.color = Light.Diffuse;// +Light.Ambient.xyz;
directLight.direction = -Light.Direction;
directLight.visible = true;
}
void getPointDirectLightIrradiance(const in DX_D3D11_CONST_LIGHT Light, const in GeometricContext geometry, out IncidentLight directLight)
{
float3 L = Light.Position - geometry.position;
directLight.direction = normalize(L);
float lightDistance = length(L);
if (((lightDistance * lightDistance) < Light.RangePow2))
{
directLight.color = Light.Diffuse;// + Light.Ambient.xyz;
directLight.color *= punctualLightIntensityToIrradianceFactorDX(lightDistance, Light.Attenuation0, Light.Attenuation1, Light.Attenuation2);
directLight.visible = true;
}
else
{
directLight.color = float3(0.0, 0.0, 0.0);
directLight.visible = false;
}
}
void getSpotDirectLightIrradiance(const in DX_D3D11_CONST_LIGHT Light, const in GeometricContext geometry, out IncidentLight directLight)
{
float3 L = Light.Position - geometry.position;
directLight.direction = normalize(L);
// ライト方向ベクトルとライト位置から頂点位置へのベクトルの内積( 即ち Cos a )を計算
float lLightDirectionCosA = dot(directLight.direction, Light.Direction * -1.f);
// スポットライト減衰計算 pow( falloff, ( ( Cos a - Cos f ) / ( Cos q - Cos f ) ) )
float spotEffect = saturate(pow(abs(max(lLightDirectionCosA - Light.SpotParam0, 0.0f) * Light.SpotParam1), Light.FallOff));
float lightDistance = length(L);
if (((lightDistance * lightDistance) < Light.RangePow2) && spotEffect > 0.f)
{
directLight.color = Light.Diffuse;// +Light.Ambient.xyz;
directLight.color *= punctualLightIntensityToIrradianceFactorDX(lightDistance, Light.Attenuation0, Light.Attenuation1, Light.Attenuation2);
directLight.color *= spotEffect;
directLight.visible = true;
}
else
{
directLight.color = float3(0.0, 0.0, 0.0);
directLight.visible = false;
}
}
// BRDFs
// Normalized Lambert
float3 DiffuseBRDF(float3 diffuseColor)
{
return diffuseColor / PI;
}
float3 F_Schlick(float3 specularColor, float3 H, float3 V)
{
return (specularColor + (1.0 - specularColor) * pow(1.0 - saturate(dot(V, H)), 5.0));
}
float D_GGX(float a, float dotNH)
{
float a2 = a * a;
float dotNH2 = dotNH * dotNH;
float d = dotNH2 * (a2 - 1.0) + 1.0;
return a2 / (PI * d * d);
}
float G_Smith_Schlick_GGX(float a, float dotNV, float dotNL)
{
float k = a * a * 0.5 + EPSILON;
float gl = dotNL / (dotNL * (1.0 - k) + k);
float gv = dotNV / (dotNV * (1.0 - k) + k);
return gl * gv;
}
// Cook-Torrance
float3 SpecularBRDF(const in IncidentLight directLight, const in GeometricContext geometry, const in Material material)
{
float3 N = geometry.normal;
float3 V = geometry.viewDir;
float3 L = directLight.direction;
float dotNL = saturate(dot(N, L));
float dotNV = saturate(dot(N, V));
float3 H = normalize(L + V);
float dotNH = saturate(dot(N, H));
float dotVH = saturate(dot(V, H));
float dotLV = saturate(dot(L, V));
float a = material.specularRoughness * material.specularRoughness;
float D = D_GGX(a, dotNH);
float G = G_Smith_Schlick_GGX(a, dotNV, dotNL);
float3 F = F_Schlick(material.specularColor, V, H);
return (F * (G * D)) / (4.0 * dotNL * dotNV + EPSILON);
}
// RenderEquations(RE)
void RE_Direct(const in IncidentLight directLight, const in GeometricContext geometry, const in Material material, inout ReflectedLight reflectedLight)
{
float p = dot(geometry.normal, directLight.direction);
p = p * 0.5f + 0.5;
p = p * p;
float dotNL = saturate(p);
float3 irradiance = dotNL * directLight.color;
// punctual light
irradiance *= PI;
reflectedLight.directDiffuse += irradiance * DiffuseBRDF(material.diffuseColor);
reflectedLight.directSpecular += irradiance * SpecularBRDF(directLight, geometry, material);
}
float4x4 InvTangentMatrix(
float3 tangent,
float3 binormal,
float3 normal) {
float4x4 mat = {float4(tangent , 0.0f),
float4(binormal, 0.0f),
float4(normal , 0.0f),
{0,0,0,1}
};
return mat; // 転置
}
PS_OUTPUT main(PS_INPUT PSInput)
{
float3 Normal = (g_NormalMapTexture.Sample(g_NormalMapSampler, PSInput.TexCoords0).rgb - 0.5f) * 2.0f;
//接空間行列でローカル法線に変換
Normal = mul(Normal, PSInput.VMat);
float metallic = 0.f;
float roughness = 0.f; //仮
float4 albedo = g_DiffuseMapTexture.Sample(g_DiffuseMapSampler, PSInput.TexCoords0);
PS_OUTPUT PSOutput;
GeometricContext geometry;
geometry.position = -PSInput.VPosition;
geometry.normal = Normal;
geometry.viewDir = normalize(PSInput.VPosition);
Material material;
material.diffuseColor = lerp(albedo.rgb, float3(0.0, 0.0, 0.0), metallic) * g_Common.Material.Diffuse.xyz;
material.specularColor = lerp(float3(0.04, 0.04, 0.04), albedo.rgb, metallic) * g_Common.Material.Specular.xyz;
material.specularRoughness = roughness;
// Lighting
ReflectedLight reflectedLight;
reflectedLight.directDiffuse = float3(0.0, 0.0, 0.0);
reflectedLight.directSpecular = float3(0.0, 0.0, 0.0);
float3 emissive = g_Common.Material.Ambient_Emissive.xyz;
float opacity = albedo.a;
IncidentLight directLight;
for (int i = 0; i < 6; ++i)
{
if (g_Common.Light[i].Type == DX_LIGHTTYPE_DIRECTIONAL)
{
getDirectionalDirectLightIrradiance(g_Common.Light[i], geometry, directLight);
RE_Direct(directLight, geometry, material, reflectedLight);
}
else if (g_Common.Light[i].Type == DX_LIGHTTYPE_SPOT)
{
getSpotDirectLightIrradiance(g_Common.Light[i], geometry, directLight);
if (directLight.visible)
{
RE_Direct(directLight, geometry, material, reflectedLight);
}
}
else if (g_Common.Light[i].Type == DX_LIGHTTYPE_POINT)
{
getPointDirectLightIrradiance(g_Common.Light[i], geometry, directLight);
if (directLight.visible)
{
RE_Direct(directLight, geometry, material, reflectedLight);
}
}
}
float3 outgoingLight = emissive + reflectedLight.directDiffuse + reflectedLight.directSpecular;
outgoingLight.r = saturate(outgoingLight.r);
outgoingLight.g = saturate(outgoingLight.g);
outgoingLight.b = saturate(outgoingLight.b);
PSOutput.Color0 = float4(outgoingLight, opacity);
PSOutput.Normal.x = (Normal.x + 1.0) / 2.0;
PSOutput.Normal.y = (Normal.y + 1.0) / 2.0;
PSOutput.Normal.z = (Normal.z + 1.0) / 2.0;
PSOutput.Normal.w = 1.0;
float4 TextureSpecularColor;
TextureSpecularColor.xyzw = 0.0;
TextureSpecularColor.xyz = g_SpecularMapTexture.Sample(g_SpecularMapSampler, PSInput.TexCoords0).xyz * PSInput.Specular.xyz;
PSOutput.Depth.x = PSInput.VPosition.z;
PSOutput.Depth.y = TextureSpecularColor.r * 0.299 + TextureSpecularColor.g * 0.587 + TextureSpecularColor.b * 0.114;
PSOutput.Depth.z = 0.0;
PSOutput.Depth.w = 1.0;
// 出力パラメータを返す
return PSOutput;
}
|
Re: mv1から直に法線マップを指定した際のシェーダーの挙動 ( No.6 ) |
- 名前:管理人 日時:2024/06/09 02:06
無事正常に表示することができたとのことで何よりです
> すいません、MV1Default_VertexLighting_PSを参考にさせていただいた際に気になったのですが、
> 以下の箇所はそれぞれでNormalに持たせるデータが異なるという認識でよろしいでしょうか?
>
> BUMPMAPの際→Normalはテクスチャ上の法線でライトのベクトルを接地空間に変換して比較
> そうでない場合→Normalはビュー法線でライトのベクトルとそのまま比較
はい、その通りです
別の形の情報なのに同じ Normal という名前の変数に値を入れてしまっているのは
あまり良くないですが… m(_ _;m
|
Re: mv1から直に法線マップを指定した際のシェーダーの挙動 ( No.7 ) |
- 名前:名無三 日時:2024/06/13 22:29
ありがとうございます、承知しました。
であればすいません、PSOutput.Normalの部分ですが出力結果の部分がテクスチャ上の法線になっているかと思います…
|
Re: mv1から直に法線マップを指定した際のシェーダーの挙動 ( No.8 ) |
- 名前:管理人 日時:2024/06/14 00:42
> であればすいません、PSOutput.Normalの部分ですが出力結果の部分がテクスチャ上の法線になっているかと思います…
…??
こちらはどのような意味でしょうか?
No.5 に載せていただいたシェーダーコードでも PSOutput.Normal は法線マップの値そのままでは無いと思いますが…
|
Re: mv1から直に法線マップを指定した際のシェーダーの挙動 ( No.9 ) |
- 名前:名無三 日時:2024/06/14 21:13
すいません、MV1Default_PixelLighting_PS.hlslのPSOutput.Normal出力に関してとなります
|
Re: mv1から直に法線マップを指定した際のシェーダーの挙動 ( No.10 ) |
- 名前:管理人 日時:2024/06/15 04:45
|
Re: mv1から直に法線マップを指定した際のシェーダーの挙動 ( No.11 ) |
- 名前:名無三(解決) 日時:2024/06/15 05:42
すいません、ありがとうございます!
|
|