add basic stereoscopic 3d support

This commit is contained in:
Shylie 2023-04-15 11:48:20 -04:00
parent 5b8816c2fe
commit 43ab9f9393
2 changed files with 143 additions and 58 deletions

View File

@ -20,24 +20,50 @@ struct vertex
float uv[2]; float uv[2];
}; };
static DVLB_s* vshaderDVLB;
static shaderProgram_s program;
static s8 spheresUniformLocation;
static s8 sphereColorsUniformLocation;
static s8 sphereLightsUniformLocation;
static s8 randUniformLocation;
static s8 shiftUniformLocation;
static constexpr unsigned int VERTEX_COUNT_W = 120;
static constexpr unsigned int VERTEX_COUNT_H = 10 * VERTEX_COUNT_W / 6;
static constexpr unsigned int VERTEX_COUNT = VERTEX_COUNT_W * VERTEX_COUNT_H;
static vertex vertexList[VERTEX_COUNT];
static u16 vertexIndices[VERTEX_COUNT * 2 + VERTEX_COUNT_H * 2];
static void* vboData;
static void* iboData;
static C3D_Tex prevFrameLeft;
static C3D_Tex prevFrameRight;
class camera class camera
{ {
public: public:
camera(const C3D_FVec lookfrom, const C3D_FVec lookat, const C3D_FVec vup, const float vfov, const float aspectRatio) camera(const C3D_FVec lookfrom, const C3D_FVec lookat, const C3D_FVec vup, const float vfov, const float aspectRatio, const float iod)
{ {
const float theta = C3D_AngleFromDegrees(vfov); const float theta = C3D_AngleFromDegrees(vfov);
const float h = tanf(theta / 2.0f); const float h = tanf(theta / 2.0f);
const float viewportHeight = 2.0f * h; const float viewportHeight = 2.0f * h;
const float viewportWidth = aspectRatio * viewportHeight; const float viewportWidth = aspectRatio * viewportHeight;
const float screen = FVec3_Distance(lookfrom, lookat) / 2.0f;
shift = iod / (-400.0f * screen * viewportWidth);
const C3D_FVec w = FVec3_Normalize(FVec3_Subtract(lookfrom, lookat)); const C3D_FVec w = FVec3_Normalize(FVec3_Subtract(lookfrom, lookat));
const C3D_FVec u = FVec3_Normalize(FVec3_Cross(vup, w)); const C3D_FVec u = FVec3_Normalize(FVec3_Cross(vup, w));
const C3D_FVec v = FVec3_Cross(w, u); const C3D_FVec v = FVec3_Cross(w, u);
origin = lookfrom; origin = FVec3_Add(lookfrom, FVec3_New(-iod / 3.0f, 0, 0));
horizontal = FVec3_Scale(u, viewportWidth); horizontal = FVec3_Scale(u, viewportWidth);
vertical = FVec3_Scale(v, viewportHeight); vertical = FVec3_Scale(v, viewportHeight);
lowerLeftCorner = FVec3_Subtract(FVec3_Add(FVec3_Scale(horizontal, -0.5f), FVec3_Scale(vertical, -0.5f)), w); lowerLeftCorner = FVec3_Add(
FVec3_Subtract(FVec3_Add(FVec3_Scale(horizontal, -0.5f), FVec3_Scale(vertical, -0.5f)), w),
FVec3_New(-iod / 3.0f, 0, 0)
);
} }
void setupFixed() const void setupFixed() const
@ -48,39 +74,27 @@ public:
*C3D_FixedAttribGetWritePtr(3) = vertical; *C3D_FixedAttribGetWritePtr(3) = vertical;
} }
void setupUniform() const
{
C3D_FVUnifSet(GPU_VERTEX_SHADER, shiftUniformLocation, shift / 200.0f, 240.0f / 256.0f, 400.0f / 512.0f, 0);
}
private: private:
C3D_FVec origin; C3D_FVec origin;
C3D_FVec lowerLeftCorner; C3D_FVec lowerLeftCorner;
C3D_FVec horizontal; C3D_FVec horizontal;
C3D_FVec vertical; C3D_FVec vertical;
float shift;
}; };
static DVLB_s* vshaderDVLB; static void setupCam(C3D_FVec lookFrom, C3D_FVec lookAt, C3D_FVec up, float iod)
static shaderProgram_s program;
static s8 spheresUniformLocation;
static s8 sphereColorsUniformLocation;
static s8 sphereLightsUniformLocation;
static s8 randUniformLocation;
static constexpr unsigned int VERTEX_COUNT_W = 150;
static constexpr unsigned int VERTEX_COUNT_H = 10 * VERTEX_COUNT_W / 6;
static constexpr unsigned int VERTEX_COUNT = VERTEX_COUNT_W * VERTEX_COUNT_H;
static vertex vertexList[VERTEX_COUNT];
static u16 vertexIndices[VERTEX_COUNT * 2 + VERTEX_COUNT_H * 2];
static void* vboData;
static void* iboData;
static C3D_Tex prevFrame;
static void setupFixed(C3D_FVec lookFrom, C3D_FVec lookAt, C3D_FVec up)
{ {
constexpr float VFOV = 90; constexpr float VFOV = 90;
constexpr float ASPECT_RATIO = 400.0f / 240.0f; constexpr float ASPECT_RATIO = C3D_AspectRatioTop;
camera cam(lookFrom, lookAt, up, VFOV, ASPECT_RATIO); camera cam(lookFrom, lookAt, up, VFOV, ASPECT_RATIO, iod);
cam.setupFixed(); cam.setupFixed();
cam.setupUniform();
} }
static float rand01() static float rand01()
@ -102,6 +116,8 @@ static C3D_FVec randvec()
while (FVec3_Magnitude(out) > 1.0f); while (FVec3_Magnitude(out) > 1.0f);
return out; return out;
return FVec4_New(0, 0, 0, 0);
} }
static void setupVertices() static void setupVertices()
@ -121,7 +137,7 @@ static void setupVertices()
v.coords[0] = 2.0f * s - 1.0f; v.coords[0] = 2.0f * s - 1.0f;
v.coords[1] = 2.0f * t - 1.0f; v.coords[1] = 2.0f * t - 1.0f;
v.coords[2] = -0.5f; v.coords[2] = -0.05f;
v.uv[0] = s * (240.0f / 256.0f); v.uv[0] = s * (240.0f / 256.0f);
v.uv[1] = t * (400.0f / 512.0f); v.uv[1] = t * (400.0f / 512.0f);
@ -168,6 +184,7 @@ static void sceneInit()
sphereColorsUniformLocation = shaderInstanceGetUniformLocation(program.vertexShader, "sphereColors"); sphereColorsUniformLocation = shaderInstanceGetUniformLocation(program.vertexShader, "sphereColors");
sphereLightsUniformLocation = shaderInstanceGetUniformLocation(program.vertexShader, "sphereLights"); sphereLightsUniformLocation = shaderInstanceGetUniformLocation(program.vertexShader, "sphereLights");
randUniformLocation = shaderInstanceGetUniformLocation(program.vertexShader, "rand"); randUniformLocation = shaderInstanceGetUniformLocation(program.vertexShader, "rand");
shiftUniformLocation = shaderInstanceGetUniformLocation(program.vertexShader, "shift");
C3D_AttrInfo* attrInfo = C3D_GetAttrInfo(); C3D_AttrInfo* attrInfo = C3D_GetAttrInfo();
AttrInfo_Init(attrInfo); AttrInfo_Init(attrInfo);
@ -254,24 +271,28 @@ static u32 getFrameNumColor(unsigned int frameNum)
int main(int argc, char* argv[]) int main(int argc, char* argv[])
{ {
gfxInitDefault(); gfxInitDefault();
gfxSet3D(true);
C3D_Init(C3D_DEFAULT_CMDBUF_SIZE); C3D_Init(C3D_DEFAULT_CMDBUF_SIZE);
C3D_RenderTarget* target = C3D_RenderTargetCreate(240, 400, GPU_RB_RGBA8, GPU_RB_DEPTH24_STENCIL8); C3D_RenderTarget* targetLeft = C3D_RenderTargetCreate(240, 400, GPU_RB_RGBA8, GPU_RB_DEPTH24_STENCIL8);
C3D_RenderTargetSetOutput(target, GFX_TOP, GFX_LEFT, DISPLAY_TRANSFER_FLAGS); C3D_RenderTargetSetOutput(targetLeft, GFX_TOP, GFX_LEFT, DISPLAY_TRANSFER_FLAGS);
C3D_RenderTarget* targetRight = C3D_RenderTargetCreate(240, 400, GPU_RB_RGBA8, GPU_RB_DEPTH24_STENCIL8);
C3D_RenderTargetSetOutput(targetRight, GFX_TOP, GFX_RIGHT, DISPLAY_TRANSFER_FLAGS);
C3D_TexInit(&prevFrame, 256, 512, GPU_RGBA8); C3D_TexInit(&prevFrameLeft, 256, 512, GPU_RGBA8);
C3D_TexBind(0, &prevFrame);
C3D_TexInit(&prevFrameRight, 256, 512, GPU_RGBA8);
sceneInit(); sceneInit();
C3D_FVec lookFrom = FVec3_New(0, 0.6125f, 0); C3D_FVec lookFrom = FVec3_New(0, 0.6125f, 0);
C3D_FVec lookAt = FVec3_New(0, 0, -1.0f); C3D_FVec lookAt = FVec3_New(0, 0, -1.0f);
C3D_FVec vup = FVec3_New(0, 1.0f, 0); C3D_FVec vup = FVec3_New(0, 1.0f, 0);
bool dirty = false; bool dirty = true;
setupFixed(lookFrom, lookAt, vup);
unsigned int frameNum = 0; unsigned int frameNum = 0;
float previousIOD = osGet3DSliderState() / 4.0f;
// Main loop // Main loop
while (aptMainLoop()) while (aptMainLoop())
@ -326,12 +347,19 @@ int main(int argc, char* argv[])
lookFrom = FVec3_Add(lookFrom, diff); lookFrom = FVec3_Add(lookFrom, diff);
const float iod = osGet3DSliderState() / 4.0f;
if (fabsf(iod - previousIOD) > 0.01f)
{
dirty = true;
}
if (dirty) if (dirty)
{ {
setupFixed(lookFrom, lookAt, vup);
frameNum = 0; frameNum = 0;
previousIOD = iod;
dirty = false; dirty = false;
} }
@ -340,26 +368,48 @@ int main(int argc, char* argv[])
C3D_TexEnvColor(C3D_GetTexEnv(0), getFrameNumColor(frameNum)); C3D_TexEnvColor(C3D_GetTexEnv(0), getFrameNumColor(frameNum));
if (C3D_FrameBegin(C3D_FRAME_SYNCDRAW)) if (frameNum < 256 && C3D_FrameBegin(C3D_FRAME_SYNCDRAW))
{ {
C3D_RenderTargetClear(target, C3D_CLEAR_ALL, 0, 0); setupCam(lookFrom, lookAt, vup, -iod);
C3D_FrameDrawOn(target); C3D_TexBind(0, &prevFrameLeft);
C3D_RenderTargetClear(targetLeft, C3D_CLEAR_ALL, 0, 0);
C3D_FrameDrawOn(targetLeft);
sceneRender(); sceneRender();
if (iod > 0)
{
setupCam(lookFrom, lookAt, vup, iod);
C3D_TexBind(0, &prevFrameRight);
C3D_RenderTargetClear(targetRight, C3D_CLEAR_ALL, 0, 0);
C3D_FrameDrawOn(targetRight);
sceneRender();
}
C3D_FrameEnd(0); C3D_FrameEnd(0);
C3D_SyncTextureCopy( C3D_SyncTextureCopy(
(u32*)target->frameBuf.colorBuf, GX_BUFFER_DIM((240 * 8 * 4) >> 4, 0), (u32*)targetLeft->frameBuf.colorBuf, GX_BUFFER_DIM((240 * 8 * 4) >> 4, 0),
(u32*)prevFrame.data + (512 - 400) * 256, GX_BUFFER_DIM((240 * 8 * 4) >> 4, ((256 - 240) * 8 * 4) >> 4), (u32*)prevFrameLeft.data + (512 - 400) * 256, GX_BUFFER_DIM((240 * 8 * 4) >> 4, ((256 - 240) * 8 * 4) >> 4),
240 * 400 * 4, FRAMEBUFFER_TRANSFER_FLAGS 240 * 400 * 4, FRAMEBUFFER_TRANSFER_FLAGS
); );
}
frameNum++; if (iod > 0)
{
C3D_SyncTextureCopy(
(u32*)targetRight->frameBuf.colorBuf, GX_BUFFER_DIM((240 * 8 * 4) >> 4, 0),
(u32*)prevFrameRight.data + (512 - 400) * 256, GX_BUFFER_DIM((240 * 8 * 4) >> 4, ((256 - 240) * 8 * 4) >> 4),
240 * 400 * 4, FRAMEBUFFER_TRANSFER_FLAGS
);
}
frameNum++;
}
} }
sceneExit(); sceneExit();
C3D_TexDelete(&prevFrame); C3D_TexDelete(&prevFrameLeft);
C3D_RenderTargetDelete(target); C3D_RenderTargetDelete(targetLeft);
C3D_Fini(); C3D_Fini();
gfxExit(); gfxExit();

View File

@ -1,11 +1,13 @@
.constf myconst(0.0, 1.0, 0.01, 1000.0) .constf myconst(0.0, 1.0, 0.001, 1000.0)
.constf myconst2(0.5, 999.0, 0.0, 0.0) .constf myconst2(0.5, 999.0, 1.1, 0.0)
.alias zeros myconst.xxxx .alias zeros myconst.xxxx
.alias halfs myconst2.xxxx .alias halfs myconst2.xxxx
.alias ones myconst.yyyy .alias ones myconst.yyyy
.alias near myconst.zzzz .alias tooclose myconst.zzzz
.alias far myconst.wwww .alias far myconst.wwww
.alias noHit myconst2.yyyy .alias noHit myconst2.yyyy
.alias defaultDist myconst.wxxx
.alias nearplane myconst2.zzzz
.consti bounceLoopParams(9, 0, 1, 0) .consti bounceLoopParams(9, 0, 1, 0)
.consti calcSphereLoopParams(3, 0, 1, 0) .consti calcSphereLoopParams(3, 0, 1, 0)
@ -26,6 +28,9 @@
; random numbers ; random numbers
.fvec rand[10] .fvec rand[10]
; stereoscopic 3d shift
.fvec shift
.in inOrigin v0 .in inOrigin v0
.in inLowerLeftCorner v1 .in inLowerLeftCorner v1
.in inHorizontal v2 .in inHorizontal v2
@ -39,12 +44,6 @@
.out outColor color .out outColor color
.proc main .proc main
; outPos = inPos
mov outPos, inPos
; outUV = inUV
mov outUV, inUV
; r1 = inOrigin ; r1 = inOrigin
mov r1, inOrigin mov r1, inOrigin
@ -60,6 +59,9 @@
; set initial color to (0, 0, 0) ; set initial color to (0, 0, 0)
mov r13.xyz, zeros mov r13.xyz, zeros
; set initial hit location to (far, far, far)
mov r15.y, far
; calculate light bounces ; calculate light bounces
for bounceLoopParams for bounceLoopParams
; setup random numbers for this iteration ; setup random numbers for this iteration
@ -87,7 +89,8 @@
; which only happens when ; which only happens when
; a ray does not hit any spheres ; a ray does not hit any spheres
cmp noHit.xyz, lt, lt, r10.xyz cmp noHit.xyz, lt, lt, r10.xyz
breakc cmp.x ;breakc cmp.x
jmpc cmp.x, labl
; multiply color by albedo ; multiply color by albedo
mul r4.xyz, r4.xyz, r10.xyz mul r4.xyz, r4.xyz, r10.xyz
@ -100,13 +103,46 @@
; set r2 to new ray direction ; set r2 to new ray direction
call diffuse call diffuse
; update distance if not set
cmp noHit, le, le, r15.y
ifc cmp.x
mov r15.y, r4.w
.end
.end .end
labl:
; copy final color to output ; copy final color to output
mov outColor.xyz, r13.xyz mov outColor.xyz, r13.xyz
; set alpha to 1 ; set alpha to 1
mov outColor.w, ones mov outColor.w, ones
; set distance
cmp noHit, le, le, r15.y
ifc cmp.x
; to (0, 0, 0, 0) since there was no hit
mov r15, zeros
.end
; clamp r15.y to [nearplane, far]
max r15.y, nearplane, r15.y
min r15.y, far, r15.y
; invert ordering for z-depth
rcp r15.z, -r15.y
; multiply distance by shift
mul r15.y, shift.x, r15.y
; outPos = inPos + shift
add outPos, inPos, r15
; assign uv coordinates
mul r15, shift.z, r15
mul r15, halfs, r15
add outUV, inUV, r15
end end
.end .end
@ -181,7 +217,7 @@
mul r9.z, r9.z, r9.x mul r9.z, r9.z, r9.x
; if root < min distance, check other root ; if root < min distance, check other root
cmp near, gt, gt, r9.z cmp tooclose, gt, gt, r9.z
jmpc cmp.x, calcSphereCheckOtherRoot jmpc cmp.x, calcSphereCheckOtherRoot
; if root > max distance, check other root ; if root > max distance, check other root
@ -198,7 +234,7 @@
mul r9.z, r9.z, r9.x mul r9.z, r9.z, r9.x
; if root < min distance, check other root ; if root < min distance, check other root
cmp near, gt, gt, r9.z cmp tooclose, gt, gt, r9.z
jmpc cmp.x, calcSphereExit jmpc cmp.x, calcSphereExit
; if root > max distance, check other root ; if root > max distance, check other root
@ -211,8 +247,7 @@
mov r4.w, r9.z mov r4.w, r9.z
; calculate new origin ; calculate new origin
mul r5.xyz, r2.xyz, r9.zzz mad r5.xyz, r2.xyz, r9.zzz, r1.xyz
add r5.xyz, r5.xyz, r1.xyz
; calculate normal ; calculate normal
add r7.xyz, r5.xyz, -r3.xyz add r7.xyz, r5.xyz, -r3.xyz