mirror of
https://github.com/mitch030504/Wiicompiled_VR_Frame.git
synced 2026-10-06 08:00:25 +02:00
Implement stereo depth and stencil support for VR cockpit rendering to fix hands getting darken by virtual screen
This commit is contained in:
1 parent
b2353e1410
commit
2a89fac79d
12 files changed
+147
-61
No files matched your search
@@ -41,7 +41,7 @@ int main() {
|
||||
native.nativeWheel=false;
|
||||
if(gfx::cockpit::geometry(native).empty()) return 1;
|
||||
for(bool bike : {false,true}) for(bool original : {false,true}) for(uint32_t samples : {1u,4u})
|
||||
for(int coverage : {0,1,2}) for(bool reversed : {false,true}) for(uint32_t eyeIndex : {0u,1u}) {
|
||||
for(bool hud : {false,true}) for(int coverage : {0,1,2}) for(bool reversed : {false,true}) for(uint32_t eyeIndex : {0u,1u}) {
|
||||
const bool occluded=coverage==1;
|
||||
gfx::StereoReplayFrame frame{};
|
||||
frame.cockpit.unitsPerMeter=100;
|
||||
@@ -60,10 +60,10 @@ int main() {
|
||||
auto output=g_device.CreateTexture(&td);
|
||||
td.sampleCount=samples;td.usage=wgpu::TextureUsage::RenderAttachment;
|
||||
auto color=g_device.CreateTexture(&td);
|
||||
td.format=wgpu::TextureFormat::Depth32Float;auto depth=g_device.CreateTexture(&td);
|
||||
td.format=wgpu::TextureFormat::Depth24PlusStencil8;auto depth=g_device.CreateTexture(&td);
|
||||
auto& eye=frame.eyes[eyeIndex];eye.target.colorView=samples==1?output.CreateView():color.CreateView();
|
||||
if(samples>1) eye.target.resolveView=output.CreateView();
|
||||
eye.target.depthView=depth.CreateView();eye.target.size={512,512,1};eye.target.msaaSamples=samples;
|
||||
eye.target.depthFormat=td.format;eye.target.depthView=depth.CreateView();eye.target.size={512,512,1};eye.target.msaaSamples=samples;
|
||||
eye.projection.m0[0]=1;eye.projection.m1[1]=1;
|
||||
eye.projection.m0[2]=eyeIndex?0.06f:-0.06f;
|
||||
auto view=gfx::cockpit::identity();view[7]=0.20f;
|
||||
@@ -72,7 +72,8 @@ int main() {
|
||||
const wgpu::RenderPassColorAttachment clear{.view=eye.target.colorView,.resolveTarget=eye.target.resolveView,
|
||||
.loadOp=wgpu::LoadOp::Clear,.storeOp=wgpu::StoreOp::Store,.clearValue={0.06,0.09,0.13,1}};
|
||||
const wgpu::RenderPassDepthStencilAttachment sceneDepth{.view=eye.target.depthView,
|
||||
.depthLoadOp=wgpu::LoadOp::Clear,.depthStoreOp=wgpu::StoreOp::Store,.depthClearValue=reversed?(occluded?0.8f:0.0f):(occluded?0.2f:1.0f)};
|
||||
.depthLoadOp=wgpu::LoadOp::Clear,.depthStoreOp=wgpu::StoreOp::Store,.depthClearValue=reversed?(occluded?0.8f:0.0f):(occluded?0.2f:1.0f),
|
||||
.stencilLoadOp=wgpu::LoadOp::Clear,.stencilStoreOp=wgpu::StoreOp::Store,.stencilClearValue=0};
|
||||
const wgpu::RenderPassDescriptor pd{.colorAttachmentCount=1,.colorAttachments=&clear,.depthStencilAttachment=&sceneDepth};
|
||||
auto pass=encoder.BeginRenderPass(&pd);
|
||||
if(coverage==2) {
|
||||
@@ -88,7 +89,7 @@ int main() {
|
||||
auto shader=g_device.CreateShaderModule(&md);
|
||||
const wgpu::ColorTargetState colorState{.format=wgpu::TextureFormat::RGBA8Unorm};
|
||||
const wgpu::FragmentState fragment{.module=shader,.entryPoint="fs",.targetCount=1,.targets=&colorState};
|
||||
const wgpu::DepthStencilState ds{.format=wgpu::TextureFormat::Depth32Float,.depthWriteEnabled=true,.depthCompare=wgpu::CompareFunction::Always};
|
||||
const wgpu::DepthStencilState ds{.format=eye.target.depthFormat,.depthWriteEnabled=true,.depthCompare=wgpu::CompareFunction::Always};
|
||||
wgpu::RenderPipelineDescriptor desc{};desc.vertex={.module=shader,.entryPoint="vs"};
|
||||
desc.fragment=&fragment;desc.depthStencil=&ds;desc.multisample.count=samples;
|
||||
auto wall=g_device.CreateRenderPipeline(&desc);pass.SetPipeline(wall);pass.Draw(6);
|
||||
@@ -96,6 +97,36 @@ int main() {
|
||||
if(coverage==2) gfx::cockpit::render(encoder,frame,eyeIndex,reversed?gfx::cockpit::SceneDepth{0,2,true}:gfx::cockpit::SceneDepth{-1,-2,true},&pass);
|
||||
pass.End();
|
||||
if(coverage!=2) gfx::cockpit::render(encoder,frame,eyeIndex,reversed?gfx::cockpit::SceneDepth{0,2,true}:gfx::cockpit::SceneDepth{-1,-2,true});
|
||||
if(hud) {
|
||||
// An opaque black screen and coloured HUD with depth testing disabled used
|
||||
// to overwrite the hands. Exercise a later pass too: the mask must survive.
|
||||
const wgpu::RenderPassColorAttachment load{.view=eye.target.colorView,.resolveTarget=eye.target.resolveView,
|
||||
.loadOp=wgpu::LoadOp::Load,.storeOp=wgpu::StoreOp::Store};
|
||||
const wgpu::RenderPassDepthStencilAttachment loadDepth{.view=eye.target.depthView,
|
||||
.depthLoadOp=wgpu::LoadOp::Load,.depthStoreOp=wgpu::StoreOp::Store,
|
||||
.stencilLoadOp=wgpu::LoadOp::Load,.stencilStoreOp=wgpu::StoreOp::Store};
|
||||
const wgpu::RenderPassDescriptor hudPass{.colorAttachmentCount=1,.colorAttachments=&load,.depthStencilAttachment=&loadDepth};
|
||||
auto overlay=encoder.BeginRenderPass(&hudPass);
|
||||
wgpu::ShaderSourceWGSL code{};
|
||||
code.code=R"(
|
||||
@vertex fn vs(@builtin(vertex_index) i:u32) -> @builtin(position) vec4f {
|
||||
let p=array<vec2f,3>(vec2f(-1,-1),vec2f(3,-1),vec2f(-1,3));
|
||||
return vec4f(p[i],0.5,1);
|
||||
}
|
||||
@fragment fn fs(@builtin(position) p:vec4f) -> @location(0) vec4f {
|
||||
return select(vec4f(0,0,0,1),vec4f(1,0,0,1),p.x<256);
|
||||
}
|
||||
)";
|
||||
wgpu::ShaderModuleDescriptor md{};md.nextInChain=&code;auto shader=g_device.CreateShaderModule(&md);
|
||||
const wgpu::ColorTargetState colorState{.format=wgpu::TextureFormat::RGBA8Unorm};
|
||||
const wgpu::FragmentState fragment{.module=shader,.entryPoint="fs",.targetCount=1,.targets=&colorState};
|
||||
const wgpu::StencilFaceState mask{.compare=wgpu::CompareFunction::Equal};
|
||||
const wgpu::DepthStencilState ds{.format=eye.target.depthFormat,.depthWriteEnabled=true,
|
||||
.depthCompare=wgpu::CompareFunction::Always,.stencilFront=mask,.stencilBack=mask,.stencilReadMask=1,.stencilWriteMask=0};
|
||||
wgpu::RenderPipelineDescriptor desc{};desc.vertex={.module=shader,.entryPoint="vs"};
|
||||
desc.fragment=&fragment;desc.depthStencil=&ds;desc.multisample.count=samples;
|
||||
auto screen=g_device.CreateRenderPipeline(&desc);overlay.SetPipeline(screen);overlay.Draw(3);overlay.End();
|
||||
}
|
||||
const wgpu::BufferDescriptor bd{.usage=wgpu::BufferUsage::CopyDst|wgpu::BufferUsage::MapRead,.size=512*512*4};
|
||||
auto readback=g_device.CreateBuffer(&bd);
|
||||
const wgpu::TexelCopyTextureInfo src{.texture=output};
|
||||
@@ -109,6 +140,13 @@ int main() {
|
||||
const auto* bytes=static_cast<const unsigned char*>(readback.GetConstMappedRange());
|
||||
size_t bright=0;
|
||||
for(size_t i=0;i<512*512;++i) if(bytes[4*i]>90&&bytes[4*i+1]>90&&bytes[4*i+2]>90) ++bright;
|
||||
if(hud && !(bytes[0]>250 && bytes[1]==0 && bytes[2]==0)) {
|
||||
std::cerr<<"HUD missing outside cockpit mask\n";++errors;
|
||||
}
|
||||
static size_t expectedBright[3][2][2]{};
|
||||
auto& expected=expectedBright[coverage][reversed][eyeIndex];
|
||||
if(!hud) expected=bright;
|
||||
else if(bright+64<expected || bright>expected+64) { std::cerr<<"HUD changed visible cockpit pixels\n";++errors; }
|
||||
if(occluded ? bright!=0 : bright<1000) { std::cerr<<"Incorrect hands/wheel occlusion\n";++errors; }
|
||||
if(coverage==2) {
|
||||
size_t left=0,right=0;
|
||||
|
||||
Reference in new issue
Block a user