-
-
Save Reputeless/f3de27e3bd221f13b3dcf3b7e92fa3bf 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> | |
void DrawBillboard(const Vec3& pos, const SizeF& size, const Mesh& mesh, const Texture& texture, const BasicCamera3D& camera) | |
{ | |
mesh.draw(camera.billboard(pos, size), texture); | |
} | |
void DrawBillboard(const Vec3& pos, double size, const Mesh& mesh, const Texture& texture, const BasicCamera3D& camera) | |
{ | |
DrawBillboard(pos, { size, size }, mesh, texture, camera); | |
} | |
void DrawBillboardPoints(const Vec3& pos, const SizeF& size, const BasicCamera3D& camera) | |
{ | |
const Mat4x4 mat = camera.billboard(pos, size); | |
const Vec3 p0 = mat.transformPoint(Vec3{ -0.5, 0.5, 0.0 }); | |
const Vec3 p1 = mat.transformPoint(Vec3{ 0.5, 0.5, 0.0 }); | |
const Vec3 p2 = mat.transformPoint(Vec3{ 0.5, -0.5, 0.0 }); | |
const Vec3 p3 = mat.transformPoint(Vec3{ -0.5, -0.5, 0.0 }); | |
Sphere{ p0, 0.08 }.draw(Linear::Palette::Yellow); | |
Sphere{ p1, 0.12 }.draw(Linear::Palette::Yellow); | |
Sphere{ p2, 0.16 }.draw(Linear::Palette::Yellow); | |
Sphere{ p3, 0.2 }.draw(Linear::Palette::Yellow); | |
} | |
void DrawBillboardPoints(const Vec3& pos, double size, const BasicCamera3D& camera) | |
{ | |
DrawBillboardPoints(pos, { size, size }, camera); | |
} | |
struct Quad3D | |
{ | |
std::array<Triangle3D, 2> triangles; | |
Optional<float> intersects(const Ray& ray) const | |
{ | |
if (auto d = ray.intersects(triangles[0])) | |
{ | |
return d; | |
} | |
if (const auto d = ray.intersects(triangles[1])) | |
{ | |
return d; | |
} | |
return none; | |
} | |
Optional<Float3> intersectsAt(const Ray& ray) const | |
{ | |
if (auto d = ray.intersectsAt(triangles[0])) | |
{ | |
return d; | |
} | |
if (const auto d = ray.intersectsAt(triangles[1])) | |
{ | |
return d; | |
} | |
return none; | |
} | |
}; | |
Quad3D BillboardToQuad(const Vec3& pos, const SizeF& size, const BasicCamera3D& camera) | |
{ | |
const Mat4x4 mat = camera.billboard(pos, size); | |
const Vec3 p0 = mat.transformPoint(Vec3{ -0.5, 0.5, 0.0 }); | |
const Vec3 p1 = mat.transformPoint(Vec3{ 0.5, 0.5, 0.0 }); | |
const Vec3 p2 = mat.transformPoint(Vec3{ 0.5, -0.5, 0.0 }); | |
const Vec3 p3 = mat.transformPoint(Vec3{ -0.5, -0.5, 0.0 }); | |
return Quad3D{{ | |
Triangle3D{ p0, p1, p2 }, | |
Triangle3D{ p0, p2, p3 }, | |
}}; | |
} | |
Quad3D BillboardToQuad(const Vec3& pos, double size, const BasicCamera3D& camera) | |
{ | |
return BillboardToQuad(pos, { size, size }, camera); | |
} | |
void Main() | |
{ | |
Window::Resize(1280, 720); | |
const ColorF backgroundColor = ColorF{ 0.4, 0.6, 0.8 }.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 Mesh billboard{ MeshData::Billboard() }; | |
const Mesh wideBillboard{ MeshData::Billboard({2, 1}) }; | |
while (System::Update()) | |
{ | |
camera.update(2.0); | |
Graphics3D::SetCameraTransform(camera); | |
const Mat4x4 billboardMat = camera.getInvView(); | |
// 3D 描画 | |
{ | |
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()); | |
DrawBillboard({ -8, 4, -4 }, 1, billboard, uvChecker, camera); | |
DrawBillboard({ 0, 4, -4 }, 2, billboard, uvChecker, camera); | |
DrawBillboard({ 8, 4, 4 }, { 8, 4 }, wideBillboard, uvChecker, camera); | |
DrawBillboardPoints({ -8, 4, -4 }, 1, camera); | |
DrawBillboardPoints({ 0, 4, -4 }, 2, camera); | |
DrawBillboardPoints({ 8, 4, 4 }, { 8, 4 }, camera); | |
const auto mouseRay = camera.screenToRay(Cursor::PosF()); | |
const auto q0 = BillboardToQuad({ -8, 4, -4 }, 1, camera); | |
const auto q1 = BillboardToQuad({ 0, 4, -4 }, 2, camera); | |
const auto q2 = BillboardToQuad({ 8, 4, 4 }, { 8, 4 }, camera); | |
if (auto pos = q0.intersectsAt(mouseRay)) | |
{ | |
Sphere{ *pos, 0.2 }.draw(Linear::Palette::Red); | |
} | |
if (auto pos = q1.intersectsAt(mouseRay)) | |
{ | |
Sphere{ *pos, 0.2 }.draw(Linear::Palette::Red); | |
} | |
if (auto pos = q2.intersectsAt(mouseRay)) | |
{ | |
Sphere{ *pos, 0.2 }.draw(Linear::Palette::Red); | |
} | |
} | |
// 3D シーンを 2D シーンに描画 | |
{ | |
Graphics3D::Flush(); | |
renderTexture.resolve(); | |
Shader::LinearToScreen(renderTexture); | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment