1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
|
// This file is part of the 64k demo project.
// ShaderToy effect implementation - REPLACE THIS LINE
// TODO: Update description, rename class
#include "gpu/effects/shadertoy_effect.h"
#include "gpu/effects/shader_composer.h"
#include "generated/assets.h"
// TODO: Rename class and adjust constructor parameters
ShaderToyEffect::ShaderToyEffect(const GpuContext& ctx) : Effect(ctx) {
}
ShaderToyEffect::~ShaderToyEffect() {
if (sampler_)
wgpuSamplerRelease(sampler_);
if (bind_group_)
wgpuBindGroupRelease(bind_group_);
if (pipeline_)
wgpuRenderPipelineRelease(pipeline_);
}
void ShaderToyEffect::init(MainSequence* demo) {
demo_ = demo;
params_.init(ctx_.device);
WGPUSamplerDescriptor sampler_desc = {};
sampler_desc.addressModeU = WGPUAddressMode_ClampToEdge;
sampler_desc.addressModeV = WGPUAddressMode_ClampToEdge;
sampler_desc.magFilter = WGPUFilterMode_Linear;
sampler_desc.minFilter = WGPUFilterMode_Linear;
sampler_desc.mipmapFilter = WGPUMipmapFilterMode_Linear;
sampler_desc.maxAnisotropy = 1;
sampler_ = wgpuDeviceCreateSampler(ctx_.device, &sampler_desc);
// TODO: Update asset name to match your shader file
size_t shader_size;
const char* shader_code = (const char*)GetAsset(
AssetId::ASSET_SHADERTOY_SHADER, &shader_size);
std::string composed = ShaderComposer::Get().Compose({}, shader_code);
WGPUShaderSourceWGSL wgsl = {};
wgsl.chain.sType = WGPUSType_ShaderSourceWGSL;
wgsl.code = str_view(composed.c_str());
WGPUShaderModuleDescriptor desc = {};
desc.nextInChain = &wgsl.chain;
WGPUShaderModule module = wgpuDeviceCreateShaderModule(ctx_.device, &desc);
const WGPUColorTargetState target = {
.format = ctx_.format,
.writeMask = WGPUColorWriteMask_All,
};
WGPUFragmentState frag = {};
frag.module = module;
frag.entryPoint = str_view("fs_main");
frag.targetCount = 1;
frag.targets = ⌖
const WGPUDepthStencilState depth_stencil = {
.format = WGPUTextureFormat_Depth24Plus,
.depthWriteEnabled = WGPUOptionalBool_False,
.depthCompare = WGPUCompareFunction_Always,
};
WGPURenderPipelineDescriptor pipeline_desc = {};
pipeline_desc.label = label_view("ShaderToyEffect");
pipeline_desc.vertex.module = module;
pipeline_desc.vertex.entryPoint = str_view("vs_main");
pipeline_desc.primitive.topology = WGPUPrimitiveTopology_TriangleList;
pipeline_desc.primitive.cullMode = WGPUCullMode_None;
pipeline_desc.depthStencil = &depth_stencil;
pipeline_desc.multisample.count = 1;
pipeline_desc.multisample.mask = 0xFFFFFFFF;
pipeline_desc.fragment = &frag;
pipeline_ = wgpuDeviceCreateRenderPipeline(ctx_.device, &pipeline_desc);
wgpuShaderModuleRelease(module);
WGPUTextureView prev_view = demo_->get_prev_texture_view();
const WGPUBindGroupEntry entries[] = {
{.binding = 0, .sampler = sampler_},
{.binding = 1, .textureView = prev_view},
{.binding = 2,
.buffer = uniforms_.get().buffer,
.size = sizeof(CommonPostProcessUniforms)},
{.binding = 3,
.buffer = params_.get().buffer,
.size = sizeof(ShaderToyParams)},
};
const WGPUBindGroupDescriptor bg_desc = {
.layout = wgpuRenderPipelineGetBindGroupLayout(pipeline_, 0),
.entryCount = 4,
.entries = entries,
};
bind_group_ = wgpuDeviceCreateBindGroup(ctx_.device, &bg_desc);
}
void ShaderToyEffect::render(WGPURenderPassEncoder pass, float time,
float beat, float intensity, float aspect_ratio) {
const CommonPostProcessUniforms uniforms = {
.resolution = {static_cast<float>(width_), static_cast<float>(height_)},
.aspect_ratio = aspect_ratio,
.time = time,
.beat = beat,
.audio_intensity = intensity,
};
uniforms_.update(ctx_.queue, uniforms);
// TODO: Update parameters based on your effect
const ShaderToyParams params = {
.param1 = 1.0f,
.param2 = beat,
};
params_.update(ctx_.queue, params);
wgpuRenderPassEncoderSetPipeline(pass, pipeline_);
wgpuRenderPassEncoderSetBindGroup(pass, 0, bind_group_, 0, nullptr);
wgpuRenderPassEncoderDraw(pass, 3, 1, 0, 0);
}
|