From dceb378111167dd29a2c87863cf9f9c982e9b790 Mon Sep 17 00:00:00 2001 From: Shylie Date: Wed, 24 Apr 2024 14:41:50 -0400 Subject: [PATCH] Allow multiple materials per scene; misc. improvements --- source/main.cpp | 54 +++++++++++++--------------- source/vshader.v.pica | 83 ++++++++++++++++++++++++++++++++----------- 2 files changed, 88 insertions(+), 49 deletions(-) diff --git a/source/main.cpp b/source/main.cpp index 36d0a56..de7a5c5 100644 --- a/source/main.cpp +++ b/source/main.cpp @@ -18,7 +18,6 @@ struct vertex float st[2]; float coords[3]; float uv[2]; - float rand[4]; }; static DVLB_s* vshaderDVLB; @@ -27,6 +26,7 @@ static s8 spheresUniformLocation; static s8 sphereColorsUniformLocation; static s8 sphereLightsUniformLocation; static s8 randUniformLocation; +static s8 calcSphereLoopParamsUniformLocation; static constexpr unsigned int VERTEX_COUNT_W = 150; static constexpr unsigned int VERTEX_COUNT_H = 10 * VERTEX_COUNT_W / 6; @@ -99,7 +99,6 @@ static float rand01() static C3D_FVec randvec() { C3D_FVec out; - out.w = rand01(); do { @@ -109,6 +108,9 @@ static C3D_FVec randvec() } while (FVec3_Magnitude(out) > 1.0f); + out = FVec3_Normalize(out); + out.w = rand01(); + return out; } @@ -123,7 +125,7 @@ static void setupVertices() const float s = static_cast(x) / VERTEX_COUNT_W; const float t = static_cast(y) / VERTEX_COUNT_H; - // swapped due to 3DS screen orientation + // s and t are swapped due to 3DS screen orientation v.st[0] = t + rand01() / VERTEX_COUNT_W; v.st[1] = s + rand01() / VERTEX_COUNT_H; @@ -141,20 +143,12 @@ static void setupVertices() static void setupRandom() { - constexpr int NUM_RAND = 20; + constexpr int NUM_RAND = 15; // needs to be the same as rand array length in vshader.v.pica C3D_FVec* randPtr = C3D_FVUnifWritePtr(GPU_VERTEX_SHADER, randUniformLocation, NUM_RAND); for (int i = 0; i < NUM_RAND; i++) { randPtr[i] = randvec(); } - - for (int i = 0; i < VERTEX_COUNT; i++) - { - vertex& v = static_cast(vboData)[i]; - - const C3D_FVec r = randvec(); - memcpy(v.rand, r.c, sizeof(r.c)); - } } static void sceneInit() @@ -184,6 +178,7 @@ static void sceneInit() sphereColorsUniformLocation = shaderInstanceGetUniformLocation(program.vertexShader, "sphereColors"); sphereLightsUniformLocation = shaderInstanceGetUniformLocation(program.vertexShader, "sphereLights"); randUniformLocation = shaderInstanceGetUniformLocation(program.vertexShader, "rand"); + calcSphereLoopParamsUniformLocation = shaderInstanceGetUniformLocation(program.vertexShader, "calcSphereLoopParams"); C3D_AttrInfo* attrInfo = C3D_GetAttrInfo(); AttrInfo_Init(attrInfo); @@ -194,14 +189,13 @@ static void sceneInit() AttrInfo_AddLoader(attrInfo, 4, GPU_FLOAT, 2); AttrInfo_AddLoader(attrInfo, 5, GPU_FLOAT, 3); AttrInfo_AddLoader(attrInfo, 6, GPU_FLOAT, 2); - AttrInfo_AddLoader(attrInfo, 7, GPU_FLOAT, 4); iboData = linearAlloc(sizeof(vertexIndices)); memcpy(iboData, vertexIndices, sizeof(vertexIndices)); C3D_BufInfo* bufInfo = C3D_GetBufInfo(); BufInfo_Init(bufInfo); - BufInfo_Add(bufInfo, vboData, sizeof(vertex), 4, 0x7654); + BufInfo_Add(bufInfo, vboData, sizeof(vertex), 3, 0x654); C3D_TexEnv* env = C3D_GetTexEnv(0); C3D_TexEnvInit(env); @@ -210,23 +204,25 @@ static void sceneInit() C3D_TexEnvFunc(env, C3D_Alpha, GPU_REPLACE); constexpr u16 NUM_SPHERES = 4; + C3D_IVUnifSet(GPU_VERTEX_SHADER, calcSphereLoopParamsUniformLocation, NUM_SPHERES - 1, 0, 1, 0); + C3D_FVec* spheres = C3D_FVUnifWritePtr(GPU_VERTEX_SHADER, spheresUniformLocation, NUM_SPHERES); - spheres[0] = FVec4_New(0.0f, -100.5f, -1.0f, 100.0f); - spheres[1] = FVec4_New(0.6f, 0.0f, -1.0f, 0.5f); - spheres[2] = FVec4_New(-0.6f, 0.0f, -1.0f, 0.5f); - spheres[3] = FVec4_New(0.0f, 10.0f, -1.0f, 9.0f); + spheres[0] = FVec4_New(0.0f, -100.5f, 0.0f, 100.0f); + spheres[1] = FVec4_New(0.6f, 0.0f, 0.0f, 0.5f); + spheres[2] = FVec4_New(-0.6f, 0.0f, 0.0f, 0.5f); + spheres[3] = FVec4_New(0.0f, 10.0f, 0.0f, 9.0f); C3D_FVec* sphereColors = C3D_FVUnifWritePtr(GPU_VERTEX_SHADER, sphereColorsUniformLocation, NUM_SPHERES); - sphereColors[0] = FVec3_New(0.9f, 0.3f, 0.3f); - sphereColors[1] = FVec3_New(0.3f, 0.9f, 0.3f); - sphereColors[2] = FVec3_New(0.3f, 0.3f, 0.9f); - sphereColors[3] = FVec3_New(1.0f, 1.0f, 1.0f); + sphereColors[0] = FVec4_New(0.9f, 0.3f, 0.3f, 0); + sphereColors[1] = FVec4_New(0.3f, 0.9f, 0.3f, 1); + sphereColors[2] = FVec4_New(0.3f, 0.3f, 0.9f, 0); + sphereColors[3] = FVec4_New(1.0f, 1.0f, 1.0f, -1); C3D_FVec* sphereLights = C3D_FVUnifWritePtr(GPU_VERTEX_SHADER, sphereLightsUniformLocation, NUM_SPHERES); - sphereLights[0] = FVec3_New(0.0f, 0.0f, 0.0f); - sphereLights[1] = FVec3_New(0.0f, 0.0f, 0.0f); - sphereLights[2] = FVec3_New(0.0f, 0.0f, 0.0f); - sphereLights[3] = FVec3_New(1.0f, 1.0f, 1.0f); + sphereLights[0] = FVec4_New(0.0f, 0.0f, 0.0f, 0); + sphereLights[1] = FVec4_New(0.0f, 0.0f, 0.0f, 0.2f); + sphereLights[2] = FVec4_New(0.0f, 0.0f, 0.0f, 0); + sphereLights[3] = FVec4_New(0.5f, 0.5f, 0.5f, 0); } static void sceneRender() @@ -280,8 +276,8 @@ int main(int argc, char* argv[]) sceneInit(); - C3D_FVec lookFrom = FVec3_New(0, 0.6125f, 0); - C3D_FVec lookAt = FVec3_New(0, 0, -1.0f); + C3D_FVec lookFrom = FVec3_New(0, 0.0f, 1.0f); + C3D_FVec lookAt = FVec3_New(0, 0, 0.0f); C3D_FVec vup = FVec3_New(0, 1.0f, 0); bool dirty = true; @@ -352,7 +348,7 @@ int main(int argc, char* argv[]) C3D_TexEnvColor(C3D_GetTexEnv(0), getFrameNumColor(frameNum)); - if (frameNum < 256 && C3D_FrameBegin(C3D_FRAME_SYNCDRAW)) + if (frameNum < 96 && C3D_FrameBegin(C3D_FRAME_SYNCDRAW)) { setupCam(lookFrom, lookAt, vup); C3D_TexBind(0, &prevFrame); diff --git a/source/vshader.v.pica b/source/vshader.v.pica index f6a27ce..7189888 100644 --- a/source/vshader.v.pica +++ b/source/vshader.v.pica @@ -7,25 +7,31 @@ .alias tooclose myconst.zzzz .alias far myconst.wwww .alias noHit myconst2.yyyy +.alias diffuseID myconst.xxxx +.alias metallicID myconst.yyyy -.consti bounceLoopParams(19, 0, 1, 0) -.consti calcSphereLoopParams(3, 0, 1, 0) +.consti bounceLoopParams(14, 0, 1, 0) + +; (NUM_SPHERES, 0, 1, 0) +.ivec calcSphereLoopParams .setb b0 true .alias true b0 ; xyz center (in world space) ; w radius (in world space) -.fvec spheres[4] +.fvec spheres[25] -; material albedo -.fvec sphereColors[4] +; material albedo (xyz) +; material id (w) +.fvec sphereColors[25] -; material emitted light -.fvec sphereLights[4] +; material emitted light (xyz) +; extra material params (w) +.fvec sphereLights[25] ; random numbers -.fvec rand[20] +.fvec rand[15] .in inOrigin v0 .in inLowerLeftCorner v1 @@ -34,7 +40,6 @@ .in inST v4 .in inPos v5 .in inUV v6 -.in inRand v7 .out outPos position .out outUV texcoord0 @@ -59,10 +64,7 @@ ; calculate light bounces for bounceLoopParams ; setup random numbers for this iteration - mul r11, rand[aL], inRand - dp3 r6.x, r11, r11 - rsq r6.x, r6.x - mul r11.xyz, r6.xxx, r11.xyz + mov r11, rand[aL] ; reset max ray distance mov r4.w, far @@ -99,7 +101,22 @@ mov r1.xyz, r5.xyz ; set r2 to new ray direction - call metallic + ; try diffuse material + cmp diffuseID.w, eq, eq, r10.w + callc cmp.x, diffuse + jmpc cmp.x, materialFound + + ; try metallic material + cmp metallicID.w, eq, eq, r10.w + callc cmp.x, metallic + jmpc cmp.x, materialFound + + ; material doesn't reflect light + ; used mostly for light-emitting objects + jmpu true, labl + + materialFound: + nop .end labl: @@ -118,6 +135,7 @@ ; Calculate Sphere Intersection ; ----------------------------- +; Performs a ray-sphere intersection test. ; ; Inputs ; ------ @@ -133,7 +151,9 @@ ; ------- ; r4.w: new min distance ; r10.xyz: albedo +; r10.w: material id ; r12.xyz: light emitted +; r12.w: extra material info ; ; Temporaries ; ----------- @@ -222,25 +242,48 @@ rcp r3.w, r3.w mul r7.xyz, r7.xyz, r3.w - ; set albedo - mov r10.xyz, sphereColors[aL].xyz + ; set albedo and material type + mov r10.xyzw, sphereColors[aL].xyzw - ; set light emitted - mov r12.xyz, sphereLights[aL].xyz + ; set light emitted and extra material info + mov r12.xyzw, sphereLights[aL].xyzw ; early exit label calcSphereExit: nop .end +; All Materials +; ------------- +; Calculates the new ray direction for a given material. +; +; Inputs +; ------ +; r1.xyz: ray origin +; r2.xyz: ray direction +; r3.xyz: sphere origin +; r3.w: sphere radius +; r4.w: min distance +; r11.xyz: random unit vector +; r11.w: random number +; +; Outputs +; ------- +; r2.xyz: new ray direction + + +; Diffuse Material +; ---------------- .proc diffuse add r2.xyz, r7.xyz, r11.xyz .end +; Metallic Material +; ----------------- .proc metallic dp3 r6.xyz, r2, r7 mul r6.xyz, twos, r6.xyz mad r2.xyz, -r6.xyz, r7.xyz, r2.xyz - ; add a bit of random "fuzziness" to the metal? - mad r2.xyz, r11.xyz, r11.w, r2.xyz + ; add a bit of random "fuzziness" to the metal + mad r2.xyz, r11.xyz, r12.w, r2.xyz .end \ No newline at end of file