-
-
Save Reputeless/eb4830bb2efb6f8734478945008f8b42 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# include <Siv3D.hpp> | |
struct PSLighting | |
{ | |
static constexpr uint32 MaxPointLights = 4; | |
struct Light | |
{ | |
Float4 position{ 0, 0, 0, 0 }; | |
Float4 diffuseColor{ 0, 0, 0, 0 }; | |
Float4 attenuation{ 1.0f, 2.0f, 1.0f, 0 }; | |
}; | |
std::array<Light, MaxPointLights> pointLights; | |
/// @brief 点光源を設定します。 | |
/// @param i 光源のインデックス。0 以上 MaxPointLights 未満である必要があります。 | |
/// @param pos 光源の位置 | |
/// @param diffuse 色 | |
/// @param r 強さ | |
void setPointLight(uint32 i, const Vec3& pos, const ColorF& diffuse, double r) | |
{ | |
pointLights[i].position = Float4{ pos, 1.0f }; | |
pointLights[i].diffuseColor = diffuse.toFloat4(); | |
pointLights[i].attenuation = Float4{ 1.0, (2.0 / r), (1.0 / (r * r)), 0.0 }; | |
} | |
/// @brief 点光源を球として描画します。 | |
/// @param i 光源のインデックス。0 以上 MaxPointLights 未満である必要があります。 | |
/// @param r 球の半径 | |
void drawPointLightAsEmissiveSphere(uint32 i, double r) | |
{ | |
const Vec3 pos = pointLights[i].position.xyz(); | |
const ColorF diffuse{ pointLights[i].diffuseColor }; | |
PhongMaterial phong; | |
phong.ambientColor = ColorF{ 0.0 }; | |
phong.diffuseColor = ColorF{ 0.0 }; | |
phong.emissionColor = diffuse; | |
Sphere{ pos, r }.draw(phong); | |
} | |
}; | |
void Main() | |
{ | |
Window::Resize(1280, 720); | |
const ColorF backgroundColor = ColorF{ 0.2, 0.2, 0.2 }.removeSRGBCurve(); | |
const Texture uvChecker{ U"example/texture/uv.png", TextureDesc::MippedSRGB }; | |
const MSRenderTexture renderTexture{ Scene::Size(), TextureFormat::R8G8B8A8_Unorm_SRGB, HasDepth::Yes }; | |
DebugCamera3D camera{ renderTexture.size(), 30_deg, Vec3{ 10, 16, -32 } }; | |
// カスタムピクセルシェーダ | |
const PixelShader ps3D = HLSL{ U"point_light.hlsl", U"PS" }; | |
ConstantBuffer<PSLighting> constantBuffer; | |
if (not ps3D) | |
{ | |
return; | |
} | |
while (System::Update()) | |
{ | |
camera.update(2.0); | |
Graphics3D::SetCameraTransform(camera); | |
// 環境光を小さくする | |
Graphics3D::SetGlobalAmbientColor(ColorF{ 0.01 }); | |
// 太陽光をオフにする | |
Graphics3D::SetSunColor(ColorF{ 0.0 }); | |
// 点光源を設定する | |
constantBuffer->setPointLight(0, Vec3{ -8, 2, -8 }, ColorF{ 1.0, 0.2, 0.0 }, 5.0); | |
constantBuffer->setPointLight(1, Cylindrical{ 12, (Scene::Time() * 30_deg), (0.5 + Periodic::Sine0_1(2s) * 2) }, ColorF{ 0.2, 1.0, 0.2 }, 5.0); | |
constantBuffer->setPointLight(2, Vec3{ 8, 2, -8 }, ColorF{ 0.2, 0.5, 1.0 }, 5.0); | |
{ | |
// カスタムシェーダを使用する | |
const ScopedCustomShader3D shader{ ps3D }; | |
// ピクセルシェーダに定数バッファを渡す | |
Graphics3D::SetPSConstantBuffer(4, constantBuffer); | |
const ScopedRenderTarget3D target{ renderTexture.clear(backgroundColor) }; | |
Plane{ 64 }.draw(uvChecker); | |
Box{ -8,2,0,4 }.draw(ColorF{ 0.8, 0.6, 0.4 }.removeSRGBCurve()); | |
Sphere{ 0,2,0,2 }.draw(ColorF{ 0.4, 0.8, 0.6 }.removeSRGBCurve()); | |
Cylinder{ 8, 2, 0, 2, 4 }.draw(ColorF{ 0.6, 0.4, 0.8 }.removeSRGBCurve()); | |
constantBuffer->drawPointLightAsEmissiveSphere(0, 0.2); | |
constantBuffer->drawPointLightAsEmissiveSphere(1, 0.2); | |
constantBuffer->drawPointLightAsEmissiveSphere(2, 0.2); | |
} | |
{ | |
Graphics3D::Flush(); | |
renderTexture.resolve(); | |
Shader::LinearToScreen(renderTexture); | |
} | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
//----------------------------------------------- | |
// | |
// This file is part of the Siv3D Engine. | |
// | |
// Copyright (c) 2008-2023 Ryo Suzuki | |
// Copyright (c) 2016-2023 OpenSiv3D Project | |
// | |
// Licensed under the MIT License. | |
// | |
//----------------------------------------------- | |
// | |
// Textures | |
// | |
Texture2D g_texture0 : register(t0); | |
SamplerState g_sampler0 : register(s0); | |
namespace s3d | |
{ | |
// | |
// VS Input | |
// | |
struct VSInput | |
{ | |
float4 position : POSITION; | |
float3 normal : NORMAL; | |
float2 uv : TEXCOORD0; | |
}; | |
// | |
// VS Output / PS Input | |
// | |
struct PSInput | |
{ | |
float4 position : SV_POSITION; | |
float3 worldPosition : TEXCOORD0; | |
float2 uv : TEXCOORD1; | |
float3 normal : TEXCOORD2; | |
}; | |
} | |
// | |
// Constant Buffer | |
// | |
cbuffer VSPerView : register(b1) | |
{ | |
row_major float4x4 g_worldToProjected; | |
} | |
cbuffer VSPerObject : register(b2) | |
{ | |
row_major float4x4 g_localToWorld; | |
} | |
cbuffer VSPerMaterial : register(b3) | |
{ | |
float4 g_uvTransform; | |
} | |
cbuffer PSPerFrame : register(b0) | |
{ | |
float3 g_globalAmbientColor; | |
float3 g_sunColor; | |
float3 g_sunDirection; | |
} | |
cbuffer PSPerView : register(b1) | |
{ | |
float3 g_eyePosition; | |
} | |
cbuffer PSPerMaterial : register(b3) | |
{ | |
float3 g_ambientColor; | |
uint g_hasTexture; | |
float4 g_diffuseColor; | |
float3 g_specularColor; | |
float g_shininess; | |
float3 g_emissionColor; | |
} | |
struct Light | |
{ | |
float4 position; | |
float4 diffuseColor; | |
float4 attenuation; | |
}; | |
static const uint MaxPointLights = 4; | |
cbuffer PSLighting : register(b4) | |
{ | |
Light g_lights[MaxPointLights]; | |
} | |
float3 CalculatePointLight(uint index, float3 surfaceNormal, float3 surfacePosition) | |
{ | |
const Light light = g_lights[index]; | |
const float3 lightPosition = light.position.xyz; | |
float3 lightDirection = (lightPosition - surfacePosition); | |
const float d = length(lightDirection); | |
const float Kc = light.attenuation.x; | |
const float Kl = light.attenuation.y; | |
const float Kq = light.attenuation.z; | |
const float f_att = 1.0 / (Kc + Kl * d + Kq * d * d); | |
lightDirection = normalize(lightDirection); | |
const float diffuseInfluence = saturate(dot(lightDirection, surfaceNormal)) * f_att; | |
return light.diffuseColor.rgb * diffuseInfluence; | |
} | |
// | |
// Functions | |
// | |
s3d::PSInput VS(s3d::VSInput input) | |
{ | |
s3d::PSInput result; | |
const float4 worldPosition = mul(input.position, g_localToWorld); | |
result.position = mul(worldPosition, g_worldToProjected); | |
result.worldPosition = worldPosition.xyz; | |
result.uv = (input.uv * g_uvTransform.xy + g_uvTransform.zw); | |
result.normal = mul(input.normal, (float3x3)g_localToWorld); | |
return result; | |
} | |
float4 GetDiffuseColor(float2 uv) | |
{ | |
float4 diffuseColor = g_diffuseColor; | |
if (g_hasTexture) | |
{ | |
diffuseColor *= g_texture0.Sample(g_sampler0, uv); | |
} | |
return diffuseColor; | |
} | |
float3 CalculateDiffuseReflection(float3 n, float3 l, float3 lightColor, float3 diffuseColor, float3 ambientColor) | |
{ | |
const float3 directColor = lightColor * saturate(dot(n, l)); | |
return ((ambientColor + directColor) * diffuseColor); | |
} | |
float3 CalculateSpecularReflection(float3 n, float3 h, float shininess, float nl, float3 lightColor, float3 specularColor) | |
{ | |
const float highlight = pow(saturate(dot(n, h)), shininess) * float(0.0 < nl); | |
return (lightColor * specularColor * highlight); | |
} | |
float4 PS(s3d::PSInput input) : SV_TARGET | |
{ | |
const float3 lightColor = g_sunColor; | |
const float3 lightDirection = g_sunDirection; | |
const float3 n = normalize(input.normal); | |
const float3 l = lightDirection; | |
const float4 diffuseColor = GetDiffuseColor(input.uv); | |
const float3 ambientColor = (g_ambientColor * g_globalAmbientColor); | |
// Diffuse | |
float3 diffuseReflection = CalculateDiffuseReflection(n, l, lightColor, diffuseColor.rgb, ambientColor); | |
// Point Light | |
for (uint i = 0; i < MaxPointLights; ++i) | |
{ | |
diffuseReflection += (diffuseColor.rgb * CalculatePointLight(i, n, input.worldPosition)); | |
} | |
// Specular | |
const float3 v = normalize(g_eyePosition - input.worldPosition); | |
const float3 h = normalize(v + lightDirection); | |
const float3 specularReflection = CalculateSpecularReflection(n, h, g_shininess, dot(n, l), lightColor, g_specularColor); | |
return float4(diffuseReflection + specularReflection + g_emissionColor, diffuseColor.a); | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment