mirror of https://github.com/AxioDL/metaforce.git
aurora: Textured quads
This commit is contained in:
parent
0703cf60b3
commit
c8c2f44fbc
|
@ -20,6 +20,7 @@ add_library(aurora STATIC
|
|||
lib/gfx/common.cpp
|
||||
lib/gfx/texture.cpp
|
||||
lib/gfx/movie_player/shader.cpp
|
||||
lib/gfx/textured_quad/shader.cpp
|
||||
# TODO move to imgui? or move imgui impl to here?
|
||||
../extern/imgui/backends/imgui_impl_sdl.cpp
|
||||
../extern/imgui/backends/imgui_impl_wgpu.cpp
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
#include "common.hpp"
|
||||
|
||||
#include "../gpu.hpp"
|
||||
#include "textured_quad//shader.hpp"
|
||||
#include "movie_player/shader.hpp"
|
||||
|
||||
#include <condition_variable>
|
||||
|
@ -17,17 +18,20 @@ using gpu::g_queue;
|
|||
|
||||
struct ShaderState {
|
||||
movie_player::State moviePlayer;
|
||||
textured_quad::State texturedQuad;
|
||||
};
|
||||
struct ShaderDrawCommand {
|
||||
ShaderType type;
|
||||
union {
|
||||
movie_player::DrawData moviePlayer;
|
||||
textured_quad::DrawData texturedQuad;
|
||||
};
|
||||
};
|
||||
struct PipelineCreateCommand {
|
||||
ShaderType type;
|
||||
union {
|
||||
movie_player::PipelineConfig moviePlayer;
|
||||
textured_quad::PipelineConfig texturedQuad;
|
||||
};
|
||||
};
|
||||
enum class CommandType {
|
||||
|
@ -135,12 +139,15 @@ void add_model(/* TODO */) noexcept {}
|
|||
void queue_aabb(const zeus::CAABox& aabb, const zeus::CColor& color, bool z_only) noexcept {
|
||||
// TODO
|
||||
}
|
||||
|
||||
void queue_fog_volume_plane(const ArrayRef<zeus::CVector4f>& verts, uint8_t pass) {
|
||||
// TODO
|
||||
}
|
||||
|
||||
void queue_fog_volume_filter(const zeus::CColor& color, bool two_way) noexcept {
|
||||
// TODO
|
||||
}
|
||||
|
||||
void queue_textured_quad_verts(CameraFilterType filter_type, const TextureHandle& texture, ZTest z_comparison,
|
||||
bool z_test, const zeus::CColor& color, const ArrayRef<zeus::CVector3f>& pos,
|
||||
const ArrayRef<zeus::CVector2f>& uvs, float lod) noexcept {
|
||||
|
@ -148,8 +155,16 @@ void queue_textured_quad_verts(CameraFilterType filter_type, const TextureHandle
|
|||
}
|
||||
void queue_textured_quad(CameraFilterType filter_type, const TextureHandle& texture, ZTest z_comparison, bool z_test,
|
||||
const zeus::CColor& color, float uv_scale, const zeus::CRectangle& rect, float z) noexcept {
|
||||
// TODO
|
||||
auto data = textured_quad::make_draw_data(g_state.texturedQuad, filter_type, texture, z_comparison, z_test, color,
|
||||
uv_scale, rect, z);
|
||||
push_draw_command({.type = ShaderType::TexturedQuad, .texturedQuad = data});
|
||||
}
|
||||
template <>
|
||||
PipelineRef pipeline_ref(textured_quad::PipelineConfig config) {
|
||||
return find_pipeline({.type = ShaderType::TexturedQuad, .texturedQuad = config},
|
||||
[=]() { return create_pipeline(g_state.texturedQuad, config); });
|
||||
}
|
||||
|
||||
void queue_colored_quad_verts(CameraFilterType filter_type, ZTest z_comparison, bool z_test, const zeus::CColor& color,
|
||||
const ArrayRef<zeus::CVector3f>& pos) noexcept {
|
||||
// TODO
|
||||
|
@ -185,7 +200,7 @@ static void pipeline_worker() {
|
|||
cb = std::move(g_queuedPipelines.front());
|
||||
}
|
||||
auto result = cb.second();
|
||||
// std::this_thread::sleep_for(std::chrono::milliseconds{1500});
|
||||
// std::this_thread::sleep_for(std::chrono::milliseconds{1500});
|
||||
{
|
||||
std::scoped_lock lock{g_pipelineMutex};
|
||||
if (g_pipelines.contains(cb.first)) {
|
||||
|
@ -230,6 +245,7 @@ void initialize() {
|
|||
}
|
||||
|
||||
g_state.moviePlayer = movie_player::construct_state();
|
||||
g_state.texturedQuad = textured_quad::construct_state();
|
||||
}
|
||||
|
||||
void shutdown() {
|
||||
|
@ -240,12 +256,18 @@ void shutdown() {
|
|||
|
||||
void render(const wgpu::RenderPassEncoder& pass) {
|
||||
{
|
||||
g_queue.WriteBuffer(g_vertexBuffer, 0, g_verts.data(), g_verts.size());
|
||||
g_queue.WriteBuffer(g_uniformBuffer, 0, g_uniforms.data(), g_uniforms.size());
|
||||
g_queue.WriteBuffer(g_indexBuffer, 0, g_indices.data(), g_indices.size());
|
||||
g_verts.clear();
|
||||
g_uniforms.clear();
|
||||
g_indices.clear();
|
||||
if (g_verts.size() > 0) {
|
||||
g_queue.WriteBuffer(g_vertexBuffer, 0, g_verts.data(), g_verts.size());
|
||||
g_verts.clear();
|
||||
}
|
||||
if (g_uniforms.size() > 0) {
|
||||
g_queue.WriteBuffer(g_uniformBuffer, 0, g_uniforms.data(), g_uniforms.size());
|
||||
g_uniforms.clear();
|
||||
}
|
||||
if (g_indices.size() > 0) {
|
||||
g_queue.WriteBuffer(g_indexBuffer, 0, g_indices.data(), g_indices.size());
|
||||
g_indices.clear();
|
||||
}
|
||||
}
|
||||
|
||||
g_currentPipeline = UINT64_MAX;
|
||||
|
@ -268,7 +290,7 @@ void render(const wgpu::RenderPassEncoder& pass) {
|
|||
// TODO
|
||||
break;
|
||||
case ShaderType::TexturedQuad:
|
||||
// TODO
|
||||
textured_quad::render(g_state.texturedQuad, draw.texturedQuad, pass);
|
||||
break;
|
||||
case ShaderType::MoviePlayer:
|
||||
movie_player::render(g_state.moviePlayer, draw.moviePlayer, pass);
|
||||
|
@ -290,6 +312,7 @@ bool bind_pipeline(PipelineRef ref, const wgpu::RenderPassEncoder& pass) {
|
|||
return false;
|
||||
}
|
||||
pass.SetPipeline(g_pipelines[ref]);
|
||||
g_currentPipeline = ref;
|
||||
return true;
|
||||
}
|
||||
|
||||
|
|
|
@ -42,25 +42,13 @@ public:
|
|||
memcpy(m_data + m_length, data, size);
|
||||
m_length += size;
|
||||
}
|
||||
|
||||
void append_zeroes(size_t size) {
|
||||
resize(m_length + size);
|
||||
memset(m_data + m_length, 0, size);
|
||||
m_length += size;
|
||||
}
|
||||
|
||||
void resize(size_t size) {
|
||||
if (size == 0) {
|
||||
clear();
|
||||
} else if (m_data == nullptr) {
|
||||
m_data = static_cast<uint8_t*>(malloc(size));
|
||||
} else if (size > m_capacity) {
|
||||
m_data = static_cast<uint8_t*>(realloc(m_data, size));
|
||||
} else {
|
||||
return;
|
||||
}
|
||||
m_capacity = size;
|
||||
}
|
||||
|
||||
void clear() {
|
||||
if (m_data != nullptr) {
|
||||
free(m_data);
|
||||
|
@ -74,18 +62,37 @@ private:
|
|||
uint8_t* m_data = nullptr;
|
||||
size_t m_length = 0;
|
||||
size_t m_capacity = 0;
|
||||
|
||||
void resize(size_t size) {
|
||||
if (size == 0) {
|
||||
clear();
|
||||
} else if (m_data == nullptr) {
|
||||
m_data = static_cast<uint8_t*>(malloc(size));
|
||||
} else if (size > m_capacity) {
|
||||
m_data = static_cast<uint8_t*>(realloc(m_data, size));
|
||||
} else {
|
||||
return;
|
||||
}
|
||||
m_capacity = size;
|
||||
}
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
struct Vec2 {
|
||||
T x{};
|
||||
T y{};
|
||||
|
||||
constexpr Vec2(T x, T y) : x(x), y(y) {}
|
||||
constexpr Vec2(const zeus::CVector2f& vec) : x(vec.x()), y(vec.y()) {}
|
||||
};
|
||||
template <typename T>
|
||||
struct Vec3 {
|
||||
T x{};
|
||||
T y{};
|
||||
T z{};
|
||||
|
||||
constexpr Vec3(T x, T y, T z) : x(x), y(y), z(z) {}
|
||||
constexpr Vec3(const zeus::CVector3f& vec) : x(vec.x()), y(vec.y()), z(vec.z()) {}
|
||||
};
|
||||
template <typename T>
|
||||
struct Vec4 {
|
||||
|
@ -93,6 +100,27 @@ struct Vec4 {
|
|||
T y{};
|
||||
T z{};
|
||||
T w{};
|
||||
|
||||
constexpr Vec4(T x, T y, T z, T w) : x(x), y(y), z(z), w(w) {}
|
||||
constexpr Vec4(const zeus::CVector4f& vec) : x(vec.x()), y(vec.y()), z(vec.z()), w(vec.w()) {}
|
||||
constexpr Vec4(const zeus::CColor& color) : x(color.r()), y(color.g()), z(color.b()), w(color.a()) {}
|
||||
};
|
||||
template <typename T>
|
||||
struct Mat4x4 {
|
||||
Vec4<T> m0{};
|
||||
Vec4<T> m1{};
|
||||
Vec4<T> m2{};
|
||||
Vec4<T> m3{};
|
||||
|
||||
constexpr Mat4x4(const Vec4<T>& m0, const Vec4<T>& m1, const Vec4<T>& m2, const Vec4<T>& m3)
|
||||
: m0(m0), m1(m1), m2(m2), m3(m3) {}
|
||||
constexpr Mat4x4(const zeus::CMatrix4f& m) : m0(m[0]), m1(m[1]), m2(m[2]), m3(m[3]) {}
|
||||
};
|
||||
constexpr Mat4x4<float> Mat4x4_Identity{
|
||||
Vec4<float>{1.f, 0.f, 0.f, 0.f},
|
||||
Vec4<float>{0.f, 1.f, 0.f, 0.f},
|
||||
Vec4<float>{0.f, 0.f, 1.f, 0.f},
|
||||
Vec4<float>{0.f, 0.f, 0.f, 1.f},
|
||||
};
|
||||
} // namespace aurora
|
||||
|
||||
|
|
|
@ -108,7 +108,6 @@ fn fs_main(in: VertexOutput) -> @location(0) vec4<f32> {
|
|||
wgpu::BindGroupEntry{
|
||||
.binding = 0,
|
||||
.buffer = g_uniformBuffer,
|
||||
.offset = 0,
|
||||
.size = uniform_size,
|
||||
},
|
||||
wgpu::BindGroupEntry{
|
||||
|
@ -223,7 +222,7 @@ DrawData make_draw_data(const State& state, const TextureHandle& tex_y, const Te
|
|||
const TextureHandle& tex_v, const zeus::CColor& color, float h_pad, float v_pad) {
|
||||
auto pipeline = pipeline_ref(PipelineConfig{});
|
||||
|
||||
const std::array<Vert, 4> verts{
|
||||
const std::array verts{
|
||||
Vert{{-h_pad, v_pad, 0.f}, {0.0, 0.0}},
|
||||
Vert{{-h_pad, -v_pad, 0.f}, {0.0, 1.0}},
|
||||
Vert{{h_pad, v_pad, 0.f}, {1.0, 0.0}},
|
||||
|
@ -232,12 +231,12 @@ DrawData make_draw_data(const State& state, const TextureHandle& tex_y, const Te
|
|||
const auto vertRange = push_verts(ArrayRef{verts});
|
||||
|
||||
const auto uniform = Uniform{
|
||||
.xf = zeus::CMatrix4f{},
|
||||
.xf = Mat4x4_Identity,
|
||||
.color = color,
|
||||
};
|
||||
const auto uniformRange = push_uniform(uniform);
|
||||
|
||||
std::array<wgpu::BindGroupEntry, 3> entries{
|
||||
const std::array entries{
|
||||
wgpu::BindGroupEntry{
|
||||
.binding = 0,
|
||||
.textureView = tex_y.ref->view,
|
||||
|
|
|
@ -24,13 +24,13 @@ struct State {
|
|||
wgpu::PipelineLayout pipelineLayout;
|
||||
};
|
||||
|
||||
struct Vert {
|
||||
struct alignas(4) Vert {
|
||||
Vec3<float> pos;
|
||||
Vec2<float> uv;
|
||||
};
|
||||
struct Uniform {
|
||||
zeus::CMatrix4f xf;
|
||||
zeus::CColor color;
|
||||
struct alignas(4) Uniform {
|
||||
Mat4x4<float> xf;
|
||||
Vec4<float> color;
|
||||
};
|
||||
|
||||
State construct_state();
|
||||
|
|
|
@ -0,0 +1,340 @@
|
|||
#include "shader.hpp"
|
||||
|
||||
#include "../../gpu.hpp"
|
||||
|
||||
#include <magic_enum.hpp>
|
||||
|
||||
namespace aurora::gfx::textured_quad {
|
||||
static logvisor::Module Log("aurora::gfx::textured_quad");
|
||||
|
||||
using gpu::g_device;
|
||||
using gpu::g_graphicsConfig;
|
||||
using gpu::utils::make_vertex_attributes;
|
||||
using gpu::utils::make_vertex_buffer_layout;
|
||||
using gpu::utils::make_vertex_state;
|
||||
|
||||
State construct_state() {
|
||||
wgpu::ShaderModuleWGSLDescriptor wgslDescriptor{};
|
||||
wgslDescriptor.source = R"""(
|
||||
struct Uniform {
|
||||
xf: mat4x4<f32>;
|
||||
color: vec4<f32>;
|
||||
lod: f32;
|
||||
};
|
||||
@group(0) @binding(0)
|
||||
var<uniform> ubuf: Uniform;
|
||||
@group(0) @binding(1)
|
||||
var texture_sampler: sampler;
|
||||
@group(1) @binding(0)
|
||||
var texture: texture_2d<f32>;
|
||||
|
||||
struct VertexOutput {
|
||||
@builtin(position) pos: vec4<f32>;
|
||||
@location(0) uv: vec2<f32>;
|
||||
};
|
||||
|
||||
@stage(vertex)
|
||||
fn vs_main(@location(0) in_pos: vec3<f32>, @location(1) in_uv: vec2<f32>) -> VertexOutput {
|
||||
var out: VertexOutput;
|
||||
out.pos = ubuf.xf * vec4<f32>(in_pos, 1.0);
|
||||
out.uv = in_uv;
|
||||
return out;
|
||||
}
|
||||
|
||||
@stage(fragment)
|
||||
fn fs_main(in: VertexOutput) -> @location(0) vec4<f32> {
|
||||
return ubuf.color * textureSampleBias(texture, texture_sampler, in.uv, ubuf.lod);
|
||||
}
|
||||
)""";
|
||||
const auto shaderDescriptor = wgpu::ShaderModuleDescriptor{
|
||||
.nextInChain = &wgslDescriptor,
|
||||
.label = "Textured Quad Shader",
|
||||
};
|
||||
auto shader = g_device.CreateShaderModule(&shaderDescriptor);
|
||||
|
||||
wgpu::SupportedLimits limits;
|
||||
g_device.GetLimits(&limits);
|
||||
const auto uniform_alignment = limits.limits.minUniformBufferOffsetAlignment;
|
||||
const auto uniform_size = ALIGN(sizeof(Uniform), uniform_alignment);
|
||||
|
||||
const std::array uniformLayoutEntries{
|
||||
wgpu::BindGroupLayoutEntry{
|
||||
.binding = 0,
|
||||
.visibility = wgpu::ShaderStage::Vertex | wgpu::ShaderStage::Fragment,
|
||||
.buffer =
|
||||
wgpu::BufferBindingLayout{
|
||||
.type = wgpu::BufferBindingType::Uniform,
|
||||
.hasDynamicOffset = true,
|
||||
.minBindingSize = uniform_size,
|
||||
},
|
||||
},
|
||||
wgpu::BindGroupLayoutEntry{
|
||||
.binding = 1,
|
||||
.visibility = wgpu::ShaderStage::Fragment,
|
||||
.sampler =
|
||||
wgpu::SamplerBindingLayout{
|
||||
.type = wgpu::SamplerBindingType::Filtering,
|
||||
},
|
||||
},
|
||||
};
|
||||
const auto uniformLayoutDescriptor = wgpu::BindGroupLayoutDescriptor{
|
||||
.label = "Textured Quad Uniform Bind Group Layout",
|
||||
.entryCount = uniformLayoutEntries.size(),
|
||||
.entries = uniformLayoutEntries.data(),
|
||||
};
|
||||
auto uniformLayout = g_device.CreateBindGroupLayout(&uniformLayoutDescriptor);
|
||||
|
||||
const auto samplerDescriptor = wgpu::SamplerDescriptor{
|
||||
.addressModeU = wgpu::AddressMode::Repeat,
|
||||
.addressModeV = wgpu::AddressMode::Repeat,
|
||||
.addressModeW = wgpu::AddressMode::Repeat,
|
||||
.magFilter = wgpu::FilterMode::Linear,
|
||||
.minFilter = wgpu::FilterMode::Linear,
|
||||
.mipmapFilter = wgpu::FilterMode::Linear,
|
||||
.maxAnisotropy = g_graphicsConfig.textureAnistropy,
|
||||
};
|
||||
auto sampler = g_device.CreateSampler(&samplerDescriptor);
|
||||
|
||||
const std::array uniformBindGroupEntries{
|
||||
wgpu::BindGroupEntry{
|
||||
.binding = 0,
|
||||
.buffer = g_uniformBuffer,
|
||||
.size = uniform_size,
|
||||
},
|
||||
wgpu::BindGroupEntry{
|
||||
.binding = 1,
|
||||
.sampler = sampler,
|
||||
},
|
||||
};
|
||||
const auto uniformBindGroupDescriptor = wgpu::BindGroupDescriptor{
|
||||
.label = "Textured Quad Uniform Bind Group",
|
||||
.layout = uniformLayout,
|
||||
.entryCount = uniformBindGroupEntries.size(),
|
||||
.entries = uniformBindGroupEntries.data(),
|
||||
};
|
||||
auto uniformBindGroup = g_device.CreateBindGroup(&uniformBindGroupDescriptor);
|
||||
|
||||
const auto textureBinding = wgpu::TextureBindingLayout{
|
||||
.sampleType = wgpu::TextureSampleType::Float,
|
||||
.viewDimension = wgpu::TextureViewDimension::e2D,
|
||||
};
|
||||
const std::array textureLayoutEntries{
|
||||
wgpu::BindGroupLayoutEntry{
|
||||
.binding = 0,
|
||||
.visibility = wgpu::ShaderStage::Fragment,
|
||||
.texture = textureBinding,
|
||||
},
|
||||
};
|
||||
const auto textureLayoutDescriptor = wgpu::BindGroupLayoutDescriptor{
|
||||
.label = "Textured Quad Texture Bind Group Layout",
|
||||
.entryCount = textureLayoutEntries.size(),
|
||||
.entries = textureLayoutEntries.data(),
|
||||
};
|
||||
auto textureLayout = g_device.CreateBindGroupLayout(&textureLayoutDescriptor);
|
||||
|
||||
const std::array bindGroupLayouts{
|
||||
uniformLayout,
|
||||
textureLayout,
|
||||
};
|
||||
const auto pipelineLayoutDescriptor = wgpu::PipelineLayoutDescriptor{
|
||||
.label = "Textured Quad Pipeline Layout",
|
||||
.bindGroupLayoutCount = bindGroupLayouts.size(),
|
||||
.bindGroupLayouts = bindGroupLayouts.data(),
|
||||
};
|
||||
auto pipelineLayout = g_device.CreatePipelineLayout(&pipelineLayoutDescriptor);
|
||||
|
||||
return {
|
||||
.shader = shader,
|
||||
.uniformLayout = uniformLayout,
|
||||
.uniformBindGroup = uniformBindGroup,
|
||||
.textureLayout = textureLayout,
|
||||
.sampler = sampler,
|
||||
.pipelineLayout = pipelineLayout,
|
||||
};
|
||||
}
|
||||
|
||||
wgpu::RenderPipeline create_pipeline(const State& state, [[maybe_unused]] PipelineConfig config) {
|
||||
const auto attributes =
|
||||
make_vertex_attributes(std::array{wgpu::VertexFormat::Float32x3, wgpu::VertexFormat::Float32x2});
|
||||
const std::array vertexBuffers{make_vertex_buffer_layout(sizeof(Vert), attributes)};
|
||||
|
||||
wgpu::CompareFunction depthCompare;
|
||||
switch (config.zComparison) {
|
||||
case ZTest::Never:
|
||||
depthCompare = wgpu::CompareFunction::Never;
|
||||
break;
|
||||
case ZTest::Less:
|
||||
depthCompare = wgpu::CompareFunction::Less;
|
||||
break;
|
||||
case ZTest::Equal:
|
||||
depthCompare = wgpu::CompareFunction::Equal;
|
||||
break;
|
||||
case ZTest::LEqual:
|
||||
depthCompare = wgpu::CompareFunction::LessEqual;
|
||||
break;
|
||||
case ZTest::Greater:
|
||||
depthCompare = wgpu::CompareFunction::Greater;
|
||||
break;
|
||||
case ZTest::NEqual:
|
||||
depthCompare = wgpu::CompareFunction::NotEqual;
|
||||
break;
|
||||
case ZTest::GEqual:
|
||||
depthCompare = wgpu::CompareFunction::GreaterEqual;
|
||||
break;
|
||||
case ZTest::Always:
|
||||
depthCompare = wgpu::CompareFunction::Always;
|
||||
break;
|
||||
}
|
||||
const auto depthStencil = wgpu::DepthStencilState{
|
||||
.format = g_graphicsConfig.depthFormat,
|
||||
.depthWriteEnabled = config.zTest,
|
||||
.depthCompare = depthCompare,
|
||||
};
|
||||
|
||||
bool alphaWrite = false;
|
||||
wgpu::BlendComponent blendComponent;
|
||||
switch (config.filterType) {
|
||||
case CameraFilterType::Multiply:
|
||||
blendComponent = wgpu::BlendComponent{
|
||||
.srcFactor = wgpu::BlendFactor::Zero,
|
||||
.dstFactor = wgpu::BlendFactor::Src,
|
||||
};
|
||||
alphaWrite = true;
|
||||
break;
|
||||
case CameraFilterType::Add:
|
||||
blendComponent = wgpu::BlendComponent{
|
||||
.srcFactor = wgpu::BlendFactor::SrcAlpha,
|
||||
.dstFactor = wgpu::BlendFactor::One,
|
||||
};
|
||||
alphaWrite = false;
|
||||
break;
|
||||
case CameraFilterType::Subtract:
|
||||
blendComponent = wgpu::BlendComponent{
|
||||
.operation = wgpu::BlendOperation::Subtract,
|
||||
.srcFactor = wgpu::BlendFactor::SrcAlpha,
|
||||
.dstFactor = wgpu::BlendFactor::One,
|
||||
};
|
||||
alphaWrite = false;
|
||||
break;
|
||||
case CameraFilterType::Blend:
|
||||
blendComponent = wgpu::BlendComponent{
|
||||
.srcFactor = wgpu::BlendFactor::SrcAlpha,
|
||||
.dstFactor = wgpu::BlendFactor::OneMinusSrcAlpha,
|
||||
};
|
||||
alphaWrite = false;
|
||||
break;
|
||||
case CameraFilterType::InvDstMultiply:
|
||||
blendComponent = wgpu::BlendComponent{
|
||||
.srcFactor = wgpu::BlendFactor::Zero,
|
||||
.dstFactor = wgpu::BlendFactor::OneMinusSrc,
|
||||
};
|
||||
alphaWrite = true;
|
||||
break;
|
||||
default:
|
||||
Log.report(logvisor::Fatal, FMT_STRING("unimplemented filter type {}"), magic_enum::enum_name(config.filterType));
|
||||
unreachable();
|
||||
}
|
||||
|
||||
const auto blendState = wgpu::BlendState{
|
||||
.color = blendComponent,
|
||||
.alpha = blendComponent,
|
||||
};
|
||||
auto writeMask = wgpu::ColorWriteMask::Red | wgpu::ColorWriteMask::Green | wgpu::ColorWriteMask::Blue;
|
||||
if (alphaWrite) {
|
||||
writeMask = writeMask | wgpu::ColorWriteMask::Alpha;
|
||||
}
|
||||
const std::array colorTargets{
|
||||
wgpu::ColorTargetState{
|
||||
.format = g_graphicsConfig.colorFormat,
|
||||
.blend = &blendState,
|
||||
.writeMask = writeMask,
|
||||
},
|
||||
};
|
||||
const auto fragmentState = wgpu::FragmentState{
|
||||
.module = state.shader,
|
||||
.entryPoint = "fs_main",
|
||||
.targetCount = colorTargets.size(),
|
||||
.targets = colorTargets.data(),
|
||||
};
|
||||
|
||||
const auto pipelineDescriptor = wgpu::RenderPipelineDescriptor{
|
||||
.label = "Textured Quad Pipeline",
|
||||
.layout = state.pipelineLayout,
|
||||
.vertex = make_vertex_state(state.shader, vertexBuffers),
|
||||
.primitive =
|
||||
wgpu::PrimitiveState{
|
||||
.topology = wgpu::PrimitiveTopology::TriangleStrip,
|
||||
},
|
||||
.depthStencil = &depthStencil,
|
||||
.multisample =
|
||||
wgpu::MultisampleState{
|
||||
.count = g_graphicsConfig.msaaSamples,
|
||||
},
|
||||
.fragment = &fragmentState,
|
||||
};
|
||||
return g_device.CreateRenderPipeline(&pipelineDescriptor);
|
||||
}
|
||||
|
||||
DrawData make_draw_data(const State& state, CameraFilterType filter_type, const TextureHandle& texture,
|
||||
ZTest z_comparison, bool z_test, const zeus::CColor& color, float uv_scale,
|
||||
const zeus::CRectangle& rect, float z) {
|
||||
auto pipeline = pipeline_ref(PipelineConfig{
|
||||
.filterType = filter_type,
|
||||
.zComparison = z_comparison,
|
||||
.zTest = z_test,
|
||||
});
|
||||
|
||||
const std::array verts{
|
||||
Vert{{0.f, 0.f, z}, {0.0, 0.0}},
|
||||
Vert{{0.f, 1.f, z}, {0.0, uv_scale}},
|
||||
Vert{{1.f, 0.f, z}, {uv_scale, 0.0}},
|
||||
Vert{{1.f, 1.f, z}, {uv_scale, uv_scale}},
|
||||
};
|
||||
const auto vertRange = push_verts(ArrayRef{verts});
|
||||
|
||||
const auto uniform = Uniform{
|
||||
.xf =
|
||||
Mat4x4<float>{
|
||||
Vec4<float>{rect.size.x() * 2.f, 0.f, 0.f, 0.f},
|
||||
Vec4<float>{0.f, rect.size.y() * 2.f, 0.f, 0.f},
|
||||
Vec4<float>{0.f, 0.f, 1.f, 0.f},
|
||||
Vec4<float>{rect.position.x() * 2.f - 1.f, rect.position.y() * 2.f - 1.f, 0.f, 1.f},
|
||||
},
|
||||
.color = color,
|
||||
.lod = 0.f,
|
||||
};
|
||||
const auto uniformRange = push_uniform(uniform);
|
||||
|
||||
const std::array entries{
|
||||
wgpu::BindGroupEntry{
|
||||
.binding = 0,
|
||||
.textureView = texture.ref->view,
|
||||
},
|
||||
};
|
||||
const auto textureBindGroup = bind_group_ref(wgpu::BindGroupDescriptor{
|
||||
.label = "Textured Quad Texture Bind Group",
|
||||
.layout = state.textureLayout,
|
||||
.entryCount = entries.size(),
|
||||
.entries = entries.data(),
|
||||
});
|
||||
|
||||
return {
|
||||
.pipeline = pipeline,
|
||||
.vertRange = vertRange,
|
||||
.uniformRange = uniformRange,
|
||||
.textureBindGroup = textureBindGroup,
|
||||
};
|
||||
}
|
||||
|
||||
void render(const State& state, const DrawData& data, const wgpu::RenderPassEncoder& pass) {
|
||||
if (!bind_pipeline(data.pipeline, pass)) {
|
||||
return;
|
||||
}
|
||||
|
||||
const std::array offsets{data.uniformRange.first};
|
||||
pass.SetBindGroup(0, state.uniformBindGroup, offsets.size(), offsets.data());
|
||||
pass.SetBindGroup(1, find_bind_group(data.textureBindGroup));
|
||||
pass.SetVertexBuffer(0, g_vertexBuffer, data.vertRange.first, data.vertRange.second);
|
||||
pass.Draw(4);
|
||||
}
|
||||
} // namespace aurora::gfx::textured_quad
|
|
@ -0,0 +1,46 @@
|
|||
#include "../common.hpp"
|
||||
|
||||
namespace aurora::gfx::textured_quad {
|
||||
struct DrawData {
|
||||
PipelineRef pipeline;
|
||||
Range vertRange;
|
||||
Range uniformRange;
|
||||
BindGroupRef textureBindGroup;
|
||||
};
|
||||
|
||||
struct PipelineConfig {
|
||||
CameraFilterType filterType;
|
||||
ZTest zComparison;
|
||||
bool zTest;
|
||||
};
|
||||
static const std::array INITIAL_PIPELINES{
|
||||
PipelineConfig{}, // TODO
|
||||
};
|
||||
|
||||
struct State {
|
||||
wgpu::ShaderModule shader;
|
||||
wgpu::BindGroupLayout uniformLayout;
|
||||
wgpu::BindGroup uniformBindGroup;
|
||||
wgpu::BindGroupLayout textureLayout;
|
||||
wgpu::Sampler sampler;
|
||||
wgpu::PipelineLayout pipelineLayout;
|
||||
};
|
||||
|
||||
struct alignas(4) Vert {
|
||||
Vec3<float> pos;
|
||||
Vec2<float> uv;
|
||||
};
|
||||
struct alignas(4) Uniform {
|
||||
Mat4x4<float> xf;
|
||||
Vec4<float> color;
|
||||
float lod;
|
||||
};
|
||||
static_assert(sizeof(Uniform) == 84);
|
||||
|
||||
State construct_state();
|
||||
wgpu::RenderPipeline create_pipeline(const State& state, [[maybe_unused]] PipelineConfig config);
|
||||
DrawData make_draw_data(const State& state, CameraFilterType filter_type, const TextureHandle& texture,
|
||||
ZTest z_comparison, bool z_test, const zeus::CColor& color, float uv_scale,
|
||||
const zeus::CRectangle& rect, float z);
|
||||
void render(const State& state, const DrawData& data, const wgpu::RenderPassEncoder& pass);
|
||||
} // namespace aurora::gfx::textured_quad
|
Loading…
Reference in New Issue